Krótko o wątkach cz.1

Wstęp

Dzisiejszy post jest jedynie wstępem do krótkiego cyklu postów, poświęconych zagadnieniom związanym z wątkami na platformie .NET.

Zajmiemy się dziś budową wątku oraz krótko opiszę sposób w jaki system wykonuje przełączanie kontekstu. Zanim jednak to nastąpi powiedzmy sobie krótko czym są wątki ?

Wątki to części programu wykonywane współbieżnie w ramach jednego procesu. To co je charakteryzuje to to, że współdzielą one pamięć adresową. To z kolei wpływa na to, że są one lżejsze od procesu, czas ich tworzenia jest szybszy i mogą one się ze sobą komunikować.

 

Budowa wątku

Każdy wątek składa się z niżej podanych rodzajów alokowanej pamięci:

Thread kernel object – Jest to specjalna struktura alokowana przez system operacyjny dla każdego tworzonego wątku. Mieści ona między innymi thread context. Thread context  jest to blok w pamięci, który zawiera zbiór wartości rejestrów procesora(o czym wspomnę nieco później). Dla CPU x64 rozmiar kotekstu wątka wynosi ok. 1240 bajtów.

Thread environment block  (Thrad Information Block) – jest to struktura, która przechowuje informacje o obecnie działającym wątku. Między innymi przechowuje ona  dane TLS(thread-local storage). Ponadto, TEB zawiera wskaźnik na „head” łańcucha wywołań obsługi błędów. Znaczy to tyle, że każde wejście w blok try danego wątku, dodaje węzeł do „head” , który jest następnie usuwany w momencie wyjścia z tego bloku. Rozmiar bloku TEB to jedna strona pamięci(4KB).

User mode stack – Jest to pamięć rezerwowana przez system o rozmiarze 1MB przeznaczona do lokalnych zmiennych i argumentów przekazywanych metodom. User mode stack zawiera również adres instrukcji która wątek powinien wykonać zaraz po tym jak zakończy się wywołanie funkcji.

Kernel mode stack  – Ze względów bezpieczeństwa, system Windows kopiuje argumenty z User mode stack do kernel mode stack, które to są przekazywane jako argumenty funkcji systemu operacyjnego. Rozmiar kernel mode stack na x64 wynosi 24 KB

 

Przełączanie kontekstu

Liczba wątków działających jednocześnie w aplikacji zależy od liczby CPU danego komputera. W danym momencie na konkretnym CPU może pracować wyłącznie jeden wątek. W przypadku gdy mamy więcej niż 1 wątków na jednym CPU wówczas w grę wchodzi przełączanie kontekstu, z jednego wątku na drugi.

Sytuacja ta wymaga jednak pomocy systemu operacyjnego, który ma za zadanie zapisanie wartości z rejestrów CPU do struktury thread context który jak wspomniałem powyżej mieści się w Thread kernel object. Następnie planista wybiera jeden wątek ze zbioru skolejkowanych i przywraca uprzednio zapisane dane ze struktury thread context do rejestrów CPU. Po tym jak przełączanie kontekstu dobiegnie końca, procesor wykonuje wątek do czasu wygaśnięcia jego przedziału czasu (ang. time slice) i cały proces przełączania kontekstu jest ponownie powtarzany.

 

Podsumowanie

Moim zdaniem, warto mieć świadomość budowy wątku jak również to w jaki sposób system wykonuje przełączenie kontekstu. Swojego czasu rozmawiałem ze znajomym o pytaniach z jakimi się spotkaliśmy będąc na różnych rozmowach kwalifikacyjnych. Jednym z nich było właśnie pytanie o rozmiar user mode stack 🙂

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *