Jaki był powód braku prewencyjności starszych jąder Linuksa?

15

Dlaczego pierwsi programiści Linuksa zdecydowali się na implementację jądra nieprzewidującego? Czy to zapisać synchronizację?

O ile mi wiadomo, Linux został opracowany na początku lat 90., kiedy komputery PC miały pojedynczy procesor. Jaką korzyść daje nieprzewidywalne jądro w takich komputerach? Dlaczego jednak przewagę tę zmniejszają procesory wielordzeniowe?

Narden
źródło

Odpowiedzi:

26

W kontekście jądra Linuksa, kiedy ludzie mówią o uprzedzeniach, często odnoszą się do zdolności jądra do samodzielnego przerywania - w zasadzie do przełączania zadań podczas działania kodu jądra. Zezwolenie na to jest dość skomplikowane, co jest prawdopodobnie głównym powodem, dla którego zajęło dużo czasu, aby jądro stało się wyprzedzające.

Początkowo większość kodu jądra i tak nie mogła zostać przerwana, ponieważ był chroniony przez dużą blokadę jądra. Blokada ta była stopniowo eliminowana z coraz większej liczby kodów jądra, umożliwiając wiele równoległych wywołań do jądra równolegle (co stało się ważniejsze, gdy systemy SMP stały się bardziej powszechne). Ale to wciąż nie czyniło samego jądra możliwym do opróżnienia; które wymagało jeszcze większego rozwoju, a kulminacją był PREEMPT_RTzestaw łatek, który ostatecznie został scalony z jądrem głównym (i mimo to był w stanie uprzedzić BKL). W dzisiejszych czasach jądro można skonfigurować tak, aby było mniej lub bardziej wyprzedzające, w zależności od oczekiwanej charakterystyki przepustowości i opóźnienia; zobacz szczegóły związane z konfiguracją jądra .

Jak widać z wyjaśnień w konfiguracji jądra, uprzedzenie wpływa na przepustowość i opóźnienie, a nie współbieżność. W systemach jednoprocesorowych wyprzedzanie jest nadal przydatne, ponieważ umożliwia przetwarzanie zdarzeń przy krótszych czasach reakcji; powoduje to jednak niższą przepustowość (ponieważ jądro spędza czas na przełączaniu zadań). Funkcja wyprzedzania pozwala dowolnemu procesorowi w systemie z jednym lub wieloma procesorami szybciej przełączać się na inne zadania. Czynnikiem ograniczającym w systemach wieloprocesorowych nie jest uprzedzenie, jest ono blokowane, duże lub w inny sposób: za każdym razem, gdy kod blokuje się, oznacza to, że inny procesor nie może rozpocząć tej samej akcji.

Stephen Kitt
źródło
12

Jądro zapobiegawcze oznacza tylko, że nie ma blokady dużego jądra .

Linux miał zapobiegawczą wielozadaniowość (tj. Kod użytkownika był możliwy do uniknięcia) od pierwszej chwili (o ile wiem, bardzo pierwszy Linux 0.0.1 przesłany przez Linusa na funet ftp server był już zapobiegawczą wielozadaniowością). Jeśli wykonałeś na przykład wiele procesów kompresji lub kompilacji, były one wykonywane równolegle od pierwszej chwili.

W przeciwieństwie do ówczesnego powszechnie używanego Win31. W Win31, jeśli zadanie pobiera procesor z „jądra”, domyślnie jego zadaniem jest określenie, kiedy przekazać kontrolę systemowi operacyjnemu (lub innym zadaniom). Jeśli proces nie miał specjalnego wsparcia dla tej funkcji (co wymagało dodatkowej pracy programistycznej), wówczas podczas wykonywania wszystkie inne zadania zostały zawieszone. Tak działały nawet najbardziej podstawowe aplikacje zintegrowane z Win31.

Zapobiegawcza wielozadaniowość oznacza, że ​​zadania nie mają możliwości przydzielenia procesora według własnego uznania. Zamiast tego, jeśli upłynie ich przedział czasowy , jądro odbierze od nich procesor. Dlatego w zapobiegawczych systemach operacyjnych źle napisany lub źle działający proces nie może zawiesić systemu operacyjnego ani uniknąć uruchomienia innych procesów. Linux zawsze zapobiegał procesom przestrzeni użytkownika.

Blokada dużego jądra oznacza, że ​​w niektórych przypadkach w przestrzeni jądra nadal mogą występować pewne blokady, uniemożliwiające innym procesom uruchomienie chronionego kodu. Na przykład nie można zamontować wielu systemów plików jednocześnie - jeśli wydano wiele poleceń montowania, były one nadal wykonywane kolejno, ponieważ montowanie elementów było wymagane do przydzielenia Big Kernel Lock.

Uaktywnienie jądra wymagało wyeliminowania tej wielkiej blokady jądra, tj. Uczynienia montowania i innych zadań, aby mogły być uruchomione jednocześnie. To była wielka praca.

Historycznie stało się to bardzo pilne ze względu na rosnącą obsługę SMP (obsługa wielu procesorów). Po raz pierwszy istniały naprawdę płyty główne z wieloma procesorami. Później wiele procesorów („rdzeni”) zostało zintegrowanych w jednym układzie, dziś naprawdę wieloprocesorowe płyty główne są już rzadkie (zwykle w kosztownych systemach serwerowych). Również naprawdę systemy jednordzeniowe (w których jest tylko jeden procesor, z jednym rdzeniem) są rzadkie.

Zatem odpowiedź na twoje pytanie nie brzmi „co było przyczyną braku prewencyjności”, ponieważ zawsze była prewencyjna. Prawdziwe pytanie brzmi: co sprawiło, że zapobiegawcze wykonanie jądra było naprawdę konieczne . Odpowiedź brzmi: rosnący stosunek systemów wieloprocesorowych i wielordzeniowych.

peterh - Przywróć Monikę
źródło
Właściwie nie rozumiałem :( Do wersji 2.4 jądra tylko procesy użytkownika były zapobiegawcze, a jądro nie było zapobiegawcze. Gdy już wcześniej komuś odpowiadałem, myślę, że powodem było zaoszczędzenie pracy nad zakleszczeniami synchronizacji, które mogłyby się zdarzyć przy zapobieganiu wdrożenie w procesie jednordzeniowym. Co myślisz?
Narden,
@Narden Nie wiem, czy to przeczytałeś. Mniej więcej do 1.3 lub 2.0, tylko jeden proces może znajdować się w przestrzeni jądra, nawet jeśli uruchomionych jest wiele procesów. Ograniczenie to zostało z grubsza wyeliminowane dzięki wersji 2.0. Do około 2.4 istniała blokada jądra Big (tj. Jednoczesne montowanie wielu systemów plików nie działało).
peterh - Przywróć Monikę
@Narden Ale to nie jest wielozadaniowość kooperacyjna, nigdy nie był potrzebny żaden proces, aby celowo oddać procesor z powrotem do harmonogramu zadań. Tak, przyczyną BKL było, że wykonanie tego poprawnie jest cholernie dużo pracy: 1) blokady muszą być podzielone 2) należy użyć struktur danych bez blokady, jeśli jest to możliwe 3) podzielone blokady prowadzą do zakleszczenia / blokady na żywo, są to zazwyczaj szczególnie brudne, trudne do naprawienia błędy, wszystkie powinny zostać znalezione i naprawione 4) wszystkie sterowniki powinny być przeniesione do zmian w interfejsie API rdzenia jądra.
peterh - Przywróć Monikę
Przeczytałem ją, gdy szukałem odpowiedzi, i jest ona również podana jako informacja w kursie, który biorę pod nazwą Systemy operacyjne.
Narden
1
Blokada Wielkiego Jądra zapobiegała przedostawaniu się innych wątków do jądra, gdy wykonywano je w jądrze. Dozwolony był tylko jeden wątek, ponieważ jądro nie było od samego początku projektowane z myślą o symetrycznym przetwarzaniu wieloprocesorowym. Jądro wyprzedzające oznacza jednak coś innego. Tradycyjnie kontekst wykonywania był zmieniany tylko wtedy, gdy jądro powróciło do przestrzeni użytkownika. W jądrze z wyprzedzającym wyprzedzeniem wątek można opróżnić w trakcie działania kodu jądra.
Johan Myréen
3

To nie jest odpowiedź techniczna, ale historyczna odpowiedź na konkretne pytanie postawione przez OP: „Jaka była przyczyna braku prewencyjnego starszych jąder Linuksa?”

(Zakładam, jak wyjaśnił @peterh w swojej odpowiedzi i komentarzach, że przez „brak uprzedzeń” OP odnosi się do jednego lub obu z faktu, że tylko jeden proces użytkownika może być w jądrze (w API) w czas i / lub blokada dużego jądra).

Linus Torvalds chciał dowiedzieć się, jak działają systemy operacyjne, a sposób, w jaki się nauczył, polegał na napisaniu jednego. Jego modelem, a także podstawowym i początkowym środowiskiem programistycznym był Minix, istniejący system operacyjny do celów edukacyjnych (tj. Nie system operacyjny), który nie był darmowy (jak wtedy w open source - nie był darmowy jak w piwie, zarówno).

Napisał więc jądro bez uprzedzeń (Blokada Wielkiego Jądra wspomniane w innych odpowiedziach), ponieważ właśnie tak to robisz, jeśli chcesz szybko uruchomić nowy system operacyjny w celach edukacyjnych: w ten sposób jest o wiele znacznie prostsze. Jądro obsługujące jednoczesne programowanie wielu programów i urządzeń użytkownika jest wystarczająco trudne - niezwykle trudno jest sprawić, aby samo jądro było współbieżne.

Gdyby wiedział, jak popularny stałby się popularny / użyteczny / ważny Linux ... prawdopodobnie zrobiłby to w ten sam sposób. (Tylko IMO, nie mam pojęcia, co on tak naprawdę myśli). Ponieważ musisz iść zanim będziesz mógł biegać.

I tak pozostało przez długi czas, ponieważ a) było wiele innych prac do zrobienia, aby Linux był tym, czym jest dzisiaj (a nawet tym, czym był wtedy) ib) jego zmiana byłaby dużym trudnym przedsięwzięciem (jak wyjaśniono w innych odpowiedziach).

Davidbak
źródło