İleti dizileri arasında hangi kaynaklar paylaşılıyor?


264

Son zamanlarda, bir röportajda bir süreç ve bir iş parçacığı arasındaki farkın ne olduğu sorusu soruldu. Gerçekten, cevabı bilmiyordum. Bir dakika düşündüm ve çok garip bir cevap verdim.

İş parçacıkları aynı belleği paylaşır, işlemler paylaşmaz. Bunu cevapladıktan sonra, görüşmeci bana kötü bir gülümseme verdi ve bana şu soruları gönderdi:

S. Bir programın bölündüğü bölümleri biliyor musunuz?

Cevabım: evet (kolay olduğunu düşündüm) Yığın, Veri, Kod, Öbek

S. Öyleyse söyle: evreler hangi segmentleri paylaşıyor?

Buna cevap veremedim ve hepsini söylemeye son verdim.

Lütfen, bir süreç ve bir iş parçacığı arasındaki fark için doğru ve etkileyici cevapları sunan var mı?


9
İş parçacıkları aynı sanal adres alanını paylaşır , işlem yapmaz.
Benoit

Yanıtlar:


177

Hemen hemen haklısınız, ancak iş parçacıkları yığın dışındaki tüm segmentleri paylaşıyor . İş parçacıklarının bağımsız çağrı yığınları vardır, ancak diğer iş parçacığı yığınlarındaki belleğe hala erişilebilir ve teorik olarak başka bir iş parçacığının yerel yığın çerçevesinde belleğe bir işaretçi tutabilirsiniz (ancak muhtemelen bu belleği koymak için daha iyi bir yer bulmalısınız!).


27
İlginç olan, iş parçacıklarının bağımsız çağrı yığınlarına sahip olmasına rağmen, diğer yığınlardaki belleğe hala erişilebilir olmasıdır.
Karthik Balaguru

1
Evet - iş parçacıkları arasındaki diğer yığınlarda belleğe erişmenin kabul edilebilir olup olmadığını merak ediyorum? Dağıtılmış bir yığına başvurmaya çalışmadığınızdan emin olduğunuz sürece, onunla ilgili bir sorun gördüğümden emin değilim?
bph

2
@bph: Başka bir iş parçacığının yığın belleğine erişmek mümkündür , ancak iyi bir yazılım mühendisliği pratiğinin çıkarlarına göre, bunun kabul edilebilir olduğunu söyleyemem .
Greg Hewgill

1
Diğer iş parçacıklarının yığınlarına erişmek, özellikle yazmak, birkaç çöp toplayıcı uygulamasıyla karışır. Ancak bu, GC uygulamasının bir hatası olarak haklı gösterilebilir.
yyny

56

Gönderen Vikipedi (: P O görüşmeci için gerçekten iyi bir cevap olacağını düşünüyorum)

İş parçacıkları, geleneksel çok görevli işletim sistemi işlemlerinden farklıdır:

  • işlemler tipik olarak bağımsızdır, iş parçacıkları ise bir işlemin alt kümeleri olarak bulunur
  • süreçler hatırı sayılır durum bilgisi taşırken süreç paylaşım durumu içinde birden çok iş parçacığı, bellek ve diğer kaynaklar
  • süreçler ayrı adres alanlarına sahipken, iş parçacıkları adres alanlarını paylaşır
  • süreçler yalnızca sistem tarafından sağlanan süreçler arası iletişim mekanizmaları aracılığıyla etkileşime girer.
  • Aynı işlemdeki iş parçacıkları arasında bağlam geçişi genellikle işlemler arasındaki bağlam geçişinden daha hızlıdır.

2
2 numaralı nokta hakkında: İş parçacıkları için de CPU bir bağlam sağlar.
Jack

49

Gerçekten belirtilmesi gereken bir şey, bu sorunun gerçekten iki yönü - teorik yönü ve uygulama yönüdür.

İlk olarak, teorik yöne bakalım. Bir işlem ve bir iş parçacığı arasındaki farkı ve aralarında paylaşılanları anlamak için bir sürecin kavramsal olarak ne olduğunu anlamalısınız.

Biz bölümünden aşağıdaki gelmiş 2.2.2 Klasik Konu Modeli içinde Modern İşletim Sistemleri 3e Tanenbaum tarafından:

Süreç modeli iki bağımsız kavrama dayanmaktadır: kaynak gruplama ve yürütme. Bazen onları ayırmak yararlı olabilir; iş parçacığı burada devreye ....

Diye devam ediyor:

Bir sürece bakmanın bir yolu, ilgili kaynakları bir arada gruplamanın bir yolu olmasıdır. Bir işlem, diğer metinlerin yanı sıra program metni ve verilerini içeren bir adres alanına sahiptir. Bu kaynaklar açık dosyaları, alt işlemleri, bekleyen alarmları, sinyal işleyicileri, muhasebe bilgilerini ve daha fazlasını içerebilir. Onları bir süreç şeklinde bir araya getirerek daha kolay yönetilebilirler. Bir sürecin sahip olduğu diğer kavram, genellikle sadece iş parçacığına kısaltılmış bir yürütme iş parçacığıdır. İş parçacığında bir sonraki çalıştırılacak komutu izleyen bir program sayacı vardır. Mevcut çalışma değişkenlerini tutan kayıtları vardır. Yürütme geçmişini içeren, çağrılan ancak henüz döndürülmeyen her yordam için bir kare içeren bir yığını vardır. Bir iş parçacığının bazı işlemlerde yürütülmesi gerekse de, iplik ve işlemi farklı kavramlardır ve ayrı ayrı ele alınabilir. Süreçler kaynakları birlikte gruplandırmak için kullanılır; evreler CPU üzerinde yürütülmesi planlanan varlıklardır.

Daha sonra aşağıdaki tabloyu sağlar:

Per process items             | Per thread items
------------------------------|-----------------
Address space                 | Program counter
Global variables              | Registers
Open files                    | Stack
Child processes               | State
Pending alarms                |
Signals and signal handlers   |
Accounting information        |

İpliklerin çalışması için ihtiyacınız olan şey yukarıdadır. Diğerlerinin de belirttiği gibi, segmentler gibi şeyler işletim sistemine bağımlı uygulama ayrıntılarıdır.


2
Bu harika bir açıklama. Ama muhtemelen bir şekilde bir "Cevap" olarak kabul edilmek üzere soruya bağlı olmalıdır
katalizör294

Tablo ile ilgili olarak, program bir kayıt değil mi? ve kayıtların değerinde yakalanan bir iş parçacığının "durumu"? Ayrıca çalıştırdıkları koda işaretçi (süreç metnine işaretçi)
eksik

29

Görüşmeciye tamamen işletim sisteminin uygulanmasına bağlı olduğunu söyleyin.

Örneğin Windows x86'yı ele alalım. Kod ve Veri olmak üzere yalnızca 2 segment vardır [1]. Her ikisi de 2GB (doğrusal, kullanıcı) adres alanının tamamına eşlenir. Temel = 0, Sınır = 2 GB. Bir tane yaparlardı, ancak x86, bir segmentin hem Okuma / Yazma hem de Yürütme olmasına izin vermez. Böylece iki tane yaptılar ve CS'yi kod tanımlayıcıya, geri kalanı (DS, ES, SS, vb.) Diğerini gösterecek şekilde ayarladılar [2]. Ama ikisi de aynı şeye işaret ediyor!

Sizinle görüşen kişi, belirtmediğine dair gizli bir varsayımda bulunmuştu ve bu da aptalca bir numara.

Yani

S. Öyleyse söyle bana hangi segment iplik payı?

Segmentler, en azından Windows'da, soru ile ilgisizdir. Konular tüm adres alanını paylaşır. Sadece 1 yığın segmenti vardır, SS ve DS, ES ve CS ile aynı şeyleri gösterir [2]. Yani tüm kanlı kullanıcı alanı . 0-2GB. Tabii ki, bu iş parçacıklarının sadece 1 yığını olduğu anlamına gelmez. Doğal olarak her birinin kendi yığını vardır, ancak x86 segmentleri bu amaç için kullanılmaz.

Belki * nix farklı bir şey yapar. Kim bilir. Sorunun dayandığı dayanak kırıldı.


  1. En azından kullanıcı alanı için.
  2. Gönderen ntsd notepad:cs=001b ss=0023 ds=0023 es=0023

1
Evet ... Segmentler işletim sistemine ve derleyiciye / bağlayıcıya bağlıdır. Bazen VERİ segmentinden ayrı bir BSS segmenti vardır. Bazen RODATA (Salt Okunur olarak işaretlenmiş sayfalarda bulunabilen sabit dizeler gibi veriler) vardır. Bazı sistemler VERİ'yi KÜÇÜK VERİ'ye (bir taban + 16 bitlik ofsetten erişilebilir) ve (FAR) VERİ'ye (erişmek için 32 bitlik ofset) bile böler. Ayrıca, iş parçacığı başına oluşturulan ek bir TLS DATA (İş Parçacığı Yerel Mağazası) Segmenti olması da mümkündür
Adisak

5
Ah, hayır! Segmentleri bölümlerle karıştırıyorsunuz! Bölümler, bağlayıcının modülü açıkladığınız şekilde parçalara (veri, rdata, metin, bss vb.) Nasıl böldüğüdür. Ancak intel / amd x86 donanımında belirtildiği gibi segmentlerden bahsediyorum. Hiç derleyici / bağlayıcı ile ilgili değildir. Umarım mantıklıdır.
Alex Budovski

Ancak, Adisak Thread Yerel mağaza hakkında haklı. İleti dizisine özeldir ve paylaşılmaz. Windows işletim sisteminin farkındayım ve diğer işletim sistemlerinden emin değilim.
Jack

20

Genellikle, ipliklere hafif ağırlık süreci denir. Belleği üç bölüme ayırırsak: Kod, veri ve Yığın. Her işlemin kendi kodu, veri ve yığın bölümleri vardır ve bu bağlamdan dolayı geçiş süresi biraz yüksektir. Bağlam değiştirme süresini azaltmak için, insanlar Veri ve kod segmentini diğer evre / süreçle paylaşan ve kendi STACK segmentine sahip olan evre kavramı geliştirdiler.


Yığını unuttun. Öbek, eğer yanılmıyorsam, iş parçacıkları arasında paylaşılmalıdır
Phate

20

Bir işlem kod, veri, yığın ve yığın parçalarına sahiptir. Şimdi, bir iş parçacığının VEYA iş parçacıklarının Talimat İşaretçisi (IP), işlemin kod segmentini gösterir. Veri ve yığın bölümleri tüm evreler tarafından paylaşılır. Peki ya yığın alanı? Aslında yığın alanı nedir? Bu, yalnızca iş parçacığının kullanması için işlem tarafından oluşturulan bir alandır ... çünkü yığınlar yığınlardan vb. Çok daha hızlı bir şekilde kullanılabilir. İşlemin yığın alanı iş parçacıkları arasında bölünür, yani 3 iş parçacığı varsa, işlemin yığın alanı 3 parçaya bölünür ve her biri 3 iş parçacığına verilir. Başka bir deyişle, her iş parçacığının kendi yığını olduğunu söylediğimizde, bu yığın aslında her iş parçacığına atanan işlem yığını alanının bir parçasıdır. Bir iş parçacığı yürütme işlemini tamamladığında, iş parçacığı yığını işlem tarafından geri kazanılır. Aslında, yalnızca bir işlem yığını iş parçacıkları arasında bölünmez, aynı zamanda bir iş parçacığının SP, PC ve durum kayıtları gibi kullandığı tüm kayıt kümeleri, sürecin kayıtlarıdır. Paylaşım söz konusu olduğunda, kod alanı, veri ve yığın alanları paylaşılırken, yığın alanı iş parçacıkları arasında paylaştırılır.


13

İş parçacıkları, kod ve veri segmentlerini ve yığını paylaşır, ancak yığını paylaşmaz.


11
"Yığındaki verilere erişme" ile yığını paylaşma arasında bir fark vardır. Bu iş parçacıklarının, yöntemleri çağırdıklarında itilmiş ve patlamış olan kendi yığınları vardır.
Kevin Peterson

2
Her ikisi de eşit derecede geçerli görüşler. Evet, her iş parçacığının iş parçacıkları ve yığınlar arasında bire bir yazışma olması ve kendi iş parçacığının kendi normal yığın kullanımı için kullandığı bir alanı olması bakımından kendi yığını vardır. Ancak aynı zamanda tamamen paylaşılan işlem kaynaklarıdır ve istenirse, herhangi bir iş parçacığı diğer herhangi bir iş parçacığının yığınına kendi kadar kolay erişebilir.
David Schwartz

@DavidSchwartz, noktanızı aşağıdaki gibi özetleyebilir miyim: Her iş parçacığının kendi yığını vardır ve yığın 2 bölümden oluşur - işlem çok iş parçacıklı olmadan önce iş parçacıkları arasında paylaşılan ilk bölüm ve ne zaman doldurulur sahibi iş parçacığı çalışıyor .. Kabul?
FaceBro

2
@nextTide İki bölüm yok. Yığınlar paylaşılır, nokta. Her iş parçacığının kendi yığını vardır, ancak bunlar da paylaşılır. Belki de iyi bir benzetme, siz ve eşinizin her birinin bir arabası varsa, ancak istediğiniz zaman birbirinizin arabalarını kullanabilirsiniz.
David Schwartz

5

İşlemler paylaşılmazken iş parçacıkları veri ve kodu paylaşır. Yığın her ikisi için de paylaşılmaz.

İşlemler, örneğin a'dan sonra belleği, daha hassas bir şekilde kodlamayı da paylaşabilir Fork(), ancak bu bir uygulama ayrıntısı ve (işletim sistemi) optimizasyonudur. Birden çok işlem tarafından paylaşılan kod (umarım) koda ilk yazmada çoğaltılır - buna yazma üzerine kopyalama denir . Ben iş parçacığı kodu için tam semantik hakkında emin değilim, ama paylaşılan kod varsayalım.

           İş parçacığını işle

   Özel özel yığın
   Özel veriler paylaşıldı
   Özel kod 1   paylaşılan 2

1 Kod mantıksal olarak gizlidir, ancak performans nedeniyle paylaşılabilir. 2 % 100 emin değilim.


Kod segmentinin (metin segmenti), verilerin aksine, çoğu mimaride neredeyse her zaman salt okunur olduğunu söyleyebilirim.
Jorge Córdoba

4

Konular her şeyi paylaşır [1]. Tüm süreç için bir adres alanı vardır.

Her iş parçacığının kendi yığını ve kayıtları vardır, ancak tüm iş parçacıklarının yığınları paylaşılan adres alanında görülebilir.

Bir iş parçacığı yığınında bir nesne atar ve adresi başka bir iş parçacığına gönderirse, her ikisinin de o nesneye eşit erişimi olur.


Aslında, daha geniş bir sorunu fark ettim: Sanırım kelimenin iki kullanımını karıştırıyorsunuz segment .

Yürütülebilir dosya (ör. ELF) için dosya biçiminde, derlenmiş kod (metin), başlatılmış veriler, bağlayıcı sembolleri, hata ayıklama bilgileri vb. İçeren bölümler olarak adlandırılabilecek farklı bölümler vardır. burada, sadece çalışma zamanı yapıları olduğu için.

Bu ikili dosya segmentleri, farklı adreslerle (örneğin kod / metin için salt okunur yürütülebilir dosya ve başlatılmış veriler için yazılamaz kopyalanmayan) işlem adresi alanına ayrı olarak eşlenebilir.

Bu adres alanının alanları, yığın ayırma ve iş parçacığı yığınları gibi farklı amaçlarla kullanılır (kural çalışma zamanı kitaplıklarınız tarafından zorlanır). Yine de hepsi sadece bellektir ve sanal 8086 modunda çalışmadığınız sürece muhtemelen bölümlere ayrılmaz. Her iş parçacığının yığını, iş parçacığı oluşturma zamanında ayrılan bir bellek yığınıdır ve geçerli yığın üst adresi bir yığın işaretçi kaydında depolanır ve her iş parçacığı, diğer kayıtlarıyla birlikte kendi yığın işaretçisini tutar.


[1] Tamam, biliyorum: sinyal maskeleri, TSS / TSD vb. Eşlenen program bölümleri de dahil olmak üzere adres alanı yine de paylaşılıyor.


3

Bir x86 çerçevesinde, en fazla segment bölünebilir (en fazla 2 ^ 16-1). ASM direktifleri SEGMENT / ENDS buna izin verir ve SEG ve OFFSET operatörleri segment kayıtlarının başlatılmasına izin verir. CS: IP genellikle yükleyici tarafından başlatılır, ancak DS, ES, SS için uygulama başlatmadan sorumludur. Birçok ortam, .code, .data, .bss, .stack vb. Gibi "basitleştirilmiş segment tanımlarına" izin verir ve ayrıca "bellek modeline" (küçük, büyük, kompakt vb.) Bağlı olarak yükleyici segment kayıtlarını başlatır buna göre. Genellikle .data, .bss, .stack ve diğer olağan segmentler (20 yıldan beri yapmadım, bu yüzden hepsini hatırlamıyorum) tek bir grupta gruplandırılmıştır - bu yüzden genellikle DS, ES ve SS, ancak bu sadece işleri basitleştirmek içindir.

Genel olarak, tüm segment kayıtları çalışma zamanında farklı değerlere sahip olabilir. Dolayısıyla, görüşme sorusu haklıydı: KOD, VERİ ve STACK'dan hangisi evreler arasında paylaşılıyor. Yığın yönetimi başka bir şeydir - sadece işletim sistemine yapılan bir çağrı dizisidir. Peki ya gömülü bir sistemde olduğu gibi bir işletim sisteminiz yoksa - kodunuzda hala yeni / silme işlemi olabilir mi?

Gençlere tavsiyem - iyi bir montaj programlama kitabı okuyun. Üniversite müfredatlarının bu açıdan oldukça fakir olduğu görülmektedir.


2

Global belleğin yanı sıra, evreler bir dizi başka niteliği de paylaşır (yani, bu özellikler bir evreye özgü olmaktan ziyade bir süreç için küreseldir). Bu özellikler aşağıdakileri içerir:

  • süreç kimliği ve üst süreç kimliği;
  • süreç grubu kimliği ve oturum kimliği;
  • kontrol terminali;
  • işlem kimlik bilgileri (kullanıcı ve grup kimlikleri);
  • açık dosya tanımlayıcıları;
  • kullanılarak oluşturulan kayıt kilitleri fcntl();
  • sinyal eğilimleri;
  • dosya sistemi ile ilgili bilgiler: umask, geçerli çalışma dizini ve kök dizini;
  • aralık zamanlayıcıları ( setitimer()) ve POSIX zamanlayıcıları ( timer_create());
  • Sistem V semafor geri alma ( semadj) değerleri (Bölüm 47.8);
  • kaynak sınırları;
  • CPU zamanı (geri döndüğü gibi times());
  • tüketilen kaynaklar (iade ettiği gibi getrusage()); ve
  • güzel değer ( setpriority()ve tarafından ayarlanır nice()).

Her bir iş parçacığı için farklı olan öznitelikler arasında şunlar vardır:

  • evre kimliği (Bölüm 29.5);
  • sinyal maskesi;
  • dişe özgü veriler (Bölüm 31.3);
  • alternatif sinyal yığını ( sigaltstack());
  • errno değişkeni;
  • kayan noktalı ortam (bkz. fenv(3));
  • gerçek zamanlı zamanlama politikası ve önceliği (Bölüm 35.2 ve 35.3);
  • CPU benzeşimi (Linux'a özgü, Bölüm 35.4'te açıklanmıştır);
  • yetenekleri (Linux'a özgü, Bölüm 39'da açıklanmıştır); ve
  • yığın (yerel değişkenler ve işlev çağrısı bağlantı bilgileri).

Alıntı: Linux Programlama Arayüzü: Linux ve UNIX Sistem Programlama El Kitabı, Michael Kerrisk , sayfa 619


0

İş parçacığı yığın yığını (iş parçacığına özgü yığın hakkında bir araştırma var) ancak geçerli uygulama yığını paylaşır. (ve tabii ki kod)


0

İş parçacığının kendi yığını varken, tüm iş parçacıkları yığın Bellek vb. Gibi sistem kaynaklarını paylaşır.

Yani ans, tüm iş parçacıklarının bir işlem için paylaştığı yığın bellek olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.