Niedawno zadano mi pytanie w wywiadzie, jaka jest różnica między procesem a wątkiem. Naprawdę nie znałem odpowiedzi. Myślałem przez chwilę i udzieliłem bardzo dziwnej odpowiedzi.
Wątki dzielą tę samą pamięć, procesy nie. Po udzieleniu odpowiedzi ankieter uśmiechnął się do mnie złośliwie i zwrócił się do mnie z następującymi pytaniami:
P: Czy znasz segmenty, na które dzieli się program?
Moja odpowiedź: tak (myślałem, że to było łatwe) Stack, Data, Code, Heap
P: Więc powiedz mi: które segmenty dzielą wątki?
Nie mogłem odpowiedzieć na to pytanie i ostatecznie powiedziałem je wszystkie.
Czy ktoś może przedstawić prawidłowe i imponujące odpowiedzi dotyczące różnicy między procesem a wątkiem?
Odpowiedzi:
Masz rację, ale wątki dzielą wszystkie segmenty oprócz stosu. Wątki mają niezależne stosy wywołań, jednak pamięć w innych stosach wątków jest nadal dostępna i teoretycznie możesz trzymać wskaźnik do pamięci w ramce lokalnego stosu innego wątku (chociaż prawdopodobnie powinieneś znaleźć lepsze miejsce na umieszczenie tej pamięci!).
źródło
Z Wikipedii (myślę, że to byłaby bardzo dobra odpowiedź dla ankietera: P)
źródło
Należy naprawdę podkreślić, że pytanie to ma dwa aspekty - aspekt teoretyczny i aspekt implementacyjny.
Najpierw spójrzmy na aspekt teoretyczny. Musisz zrozumieć, czym jest proces, aby zrozumieć różnicę między procesem a wątkiem i co jest między nimi wspólne.
W sekcji 2.2.2 Klasyczny model wątku w nowoczesnych systemach operacyjnych 3e autorstwa Tanenbaum:
On kontynuuje:
Dalej znajduje się następująca tabela:
To, czego potrzebujesz, aby wątki działały. Jak zauważyli inni, segmenty są szczegółami implementacji zależnymi od systemu operacyjnego.
źródło
Powiedz ankieterowi, że zależy to wyłącznie od wdrożenia systemu operacyjnego.
Weźmy na przykład Windows x86. Istnieją tylko 2 segmenty [1], Kod i Dane. Oba są odwzorowane na całą przestrzeń adresową 2 GB (liniową, użytkownika). Baza = 0, limit = 2 GB. Zrobiliby taki, ale x86 nie pozwala na segmentowanie zarówno odczytu / zapisu, jak i wykonania. Zrobili więc dwa i ustawili CS, aby wskazywał deskryptor kodu, a reszta (DS, ES, SS itd.) Wskazywała na drugi [2]. Ale oba wskazują na te same rzeczy!
Osoba przeprowadzająca wywiad z tobą ukryła założenie, że nie oświadczył, a to głupia sztuczka do wyciągnięcia.
Jeśli chodzi o
Segmenty nie mają znaczenia dla pytania, przynajmniej w systemie Windows. Wątki dzielą całą przestrzeń adresową. Jest tylko 1 segment stosu, SS, i wskazuje dokładnie na te same rzeczy, co DS, ES i CS [2]. To znaczy cała cholerna przestrzeń użytkownika . 0–2 GB Oczywiście nie oznacza to, że wątki mają tylko 1 stos. Oczywiście każdy ma swój własny stos, ale do tego celu nie są używane segmenty x86.
Może * nix robi coś innego. Kto wie. Przesłanka, na której opierało się pytanie, została złamana.
ntsd notepad
:cs=001b ss=0023 ds=0023 es=0023
źródło
Ogólnie wątki nazywane są lekkimi procesami. Jeśli podzielimy pamięć na trzy sekcje, będzie to: Kod, dane i Stos. Każdy proces ma swój własny kod, sekcje danych i stosu, dlatego czas przełączania kontekstu jest nieco długi. Aby skrócić czas przełączania kontekstu, ludzie wymyślili koncepcję wątku, który dzieli segment danych i kodu z innym wątkiem / procesem i ma własny segment STOSOWANIA.
źródło
Proces ma segmenty kodu, danych, sterty i stosu. Teraz wskaźnik instrukcji (IP) wątku LUB wątków wskazuje segment kodu procesu. Segmenty danych i sterty są wspólne dla wszystkich wątków. A co z obszarem stosu? Co to właściwie jest obszar stosu? Jest to obszar utworzony przez proces tylko do użycia przez wątek ... ponieważ stosy mogą być używane znacznie szybciej niż stosy itp. Obszar stosu procesu jest podzielony na wątki, tzn. Jeśli są 3 wątki, wówczas obszar stosu procesu jest podzielony na 3 części, a każda z nich jest podana do 3 wątków. Innymi słowy, kiedy mówimy, że każdy wątek ma swój własny stos, stos ten jest w rzeczywistości częścią obszaru stosu procesu przypisanego do każdego wątku. Po zakończeniu wykonywania wątku stos wątku jest odzyskiwany przez proces. W rzeczywistości, nie tylko stos procesu jest podzielony na wątki, ale cały zestaw rejestrów używanych przez wątek, takich jak SP, PC i rejestry stanu, są rejestrami procesu. Jeśli chodzi o udostępnianie, obszary kodu, danych i sterty są wspólne, a obszar stosu jest po prostu podzielony na wątki.
źródło
Wątki dzielą kod i segmenty danych oraz stertę, ale nie dzielą stosu.
źródło
Wątki współużytkują dane i kod, podczas gdy procesy nie. Stos nie jest udostępniany dla obu.
Procesy mogą również współużytkować pamięć, a dokładniej kod, na przykład po a
Fork()
, ale jest to szczegół implementacji i optymalizacja (systemu operacyjnego). Kod współdzielony przez wiele procesów zostanie (mam nadzieję) zduplikowany przy pierwszym zapisie do kodu - jest to znane jako kopiowanie przy zapisie . Nie jestem pewien co do dokładnej semantyki dla kodu wątków, ale zakładam kod współdzielony.1 Kod jest logicznie prywatny, ale może być udostępniany ze względu na wydajność. 2 Nie jestem w 100% pewien.
źródło
Wątki udostępniają wszystko [1]. Dla całego procesu istnieje jedna przestrzeń adresowa.
Każdy wątek ma swój własny stos i rejestry, ale wszystkie stosy wątków są widoczne we wspólnej przestrzeni adresowej.
Jeśli jeden wątek przydzieli jakiś obiekt na stosie i wyśle adres do innego wątku, oba będą miały równy dostęp do tego obiektu.
W rzeczywistości, po prostu zauważyłem szerszy problem: Myślę, że mylące dwa zastosowania tego słowa segmencie .
Format pliku wykonywalnego (np. ELF) zawiera odrębne sekcje, które można nazwać segmentami, zawierającymi skompilowany kod (tekst), zainicjowane dane, symbole linkera, informacje debugowania itp. Nie ma segmentów sterty lub stosu tutaj, ponieważ są to konstrukcje tylko do uruchamiania.
Te segmenty plików binarnych mogą być mapowane osobno w przestrzeni adresowej procesu, z różnymi uprawnieniami (np. Plik wykonywalny tylko do odczytu dla kodu / tekstu i plik wykonywalny kopiowania przy zapisie dla danych inicjowanych).
Obszary tej przestrzeni adresowej są wykorzystywane do różnych celów, takich jak alokacja sterty i stosy wątków, zgodnie z konwencją (wymuszoną przez biblioteki środowiska wykonawczego języka). To wszystko jest tylko pamięć i prawdopodobnie nie jest podzielona na segmenty, chyba że pracujesz w trybie wirtualnym 8086. Stos każdego wątku jest fragmentem pamięci przydzielanej podczas tworzenia wątku, przy czym bieżący górny adres stosu jest przechowywany w rejestrze wskaźnika stosu, a każdy wątek utrzymuje swój własny wskaźnik stosu wraz z innymi rejestrami.
[1] OK, wiem: maski sygnałów, TSS / TSD itp. Przestrzeń adresowa, w tym wszystkie jej zmapowane segmenty programu, są jednak nadal współdzielone.
źródło
W środowisku x86 można podzielić tyle segmentów (do 2 ^ 16-1). Na to pozwalają dyrektywy ASM SEGMENT / ENDS, a operatorzy SEG i OFFSET umożliwiają inicjalizację rejestrów segmentów. CS: IP są zwykle inicjowane przez moduł ładujący, ale w przypadku DS, ES, SS aplikacja jest odpowiedzialna za inicjalizację. Wiele środowisk pozwala na tak zwane „uproszczone definicje segmentów”, takie jak .code, .data, .bss, .stack itp. Oraz, w zależności od „modelu pamięci” (mały, duży, kompaktowy itp.), Moduł ładujący inicjuje rejestry segmentów odpowiednio. Zwykle .data, .bss, .stack i inne zwykłe segmenty (nie robiłem tego od 20 lat, więc nie pamiętam wszystkich) są zgrupowane w jednej grupie - dlatego zwykle punkty DS, ES i SS są ten sam obszar, ale ma to jedynie na celu uproszczenie.
Zasadniczo wszystkie rejestry segmentów mogą mieć różne wartości w czasie wykonywania. Pytanie w rozmowie kwalifikacyjnej było więc prawidłowe: który z KODÓW, DANYCH i STOSOWANIA są współużytkowane przez wątki. Zarządzanie stertami to coś innego - to po prostu sekwencja połączeń z systemem operacyjnym. Ale co, jeśli w ogóle nie masz systemu operacyjnego, na przykład w systemie wbudowanym - czy nadal możesz mieć nowy / usunąć w kodzie?
Moja rada dla młodych ludzi - przeczytaj dobrą książkę do programowania w asemblerze. Wydaje się, że pod tym względem programy uniwersyteckie są dość słabe.
źródło
Fragment: Interfejs programowania systemu Linux: Podręcznik programowania systemu Linux i UNIX, Michael Kerrisk , strona 619
źródło
Wątek udostępnia stertę (są badania nad stertą dla określonego wątku), ale bieżąca implementacja udostępnia stertę. (i oczywiście kod)
źródło
W trakcie procesu wszystkie wątki współużytkują zasoby systemowe, takie jak Pamięć sterty itp., Podczas gdy wątek ma własny stos
Więc twoja ans powinna być pamięcią sterty, którą wszystkie wątki współużytkują dla procesu.
źródło