Dlaczego jądro Linuksa ma ponad 15 milionów linii kodu? [Zamknięte]

109

Jaka jest zawartość tej monolitycznej bazy kodu?

Rozumiem obsługę architektury procesorów, bezpieczeństwo i wirtualizację, ale nie wyobrażam sobie, aby było to więcej niż 600 000 linii.

Jakie są historyczne i obecne powody, dla których sterowniki są zawarte w bazie kodu jądra?

Czy te ponad 15 milionów linii obejmuje każdy sterownik dla każdego elementu sprzętu? Jeśli tak, to nasuwa się pytanie, dlaczego sterowniki są osadzone w jądrze, a nie oddzielne pakiety, które są automatycznie wykrywane i instalowane na podstawie identyfikatorów sprzętu?

Czy rozmiar kodu stanowi problem w przypadku urządzeń o ograniczonej pamięci lub o ograniczonej pamięci?

Wygląda na to, że gdyby to wszystko było osadzone, zwiększyłoby rozmiar jądra dla ograniczonych przestrzennie urządzeń ARM. Czy preprocesor usuwa wiele linii? Nazywaj mnie szalonym, ale nie wyobrażam sobie maszyny wymagającej tyle logiki, aby uruchomić to, co rozumiem, to role jądra.

Czy istnieją dowody, że rozmiar będzie problemem za ponad 50 lat ze względu na jego pozornie stale rosnący charakter?

Dołączenie sterowników oznacza, że ​​będzie rosnąć wraz z produkcją sprzętu.

EDYCJA : Dla tych, którzy myślą, że taka jest natura jąder, po kilku badaniach zdałem sobie sprawę, że nie zawsze. Jądro nie musi być tak duże, ponieważ mikrojądro Carnegie Mellon Mach zostało wymienione jako przykład „zwykle poniżej 10 000 wierszy kodu”

Jonathan
źródło
9
W 2012 roku miał ponad 5 milionów linii tylko dla kierowców. 1,9 miliona linii do obsługi różnych architektur procesorów. Więcej informacji h-online.com/open/features/…
steve
11
Tak, napisałem kod kompilatora, analizatora leksykalnego i generatora kodu bajtowego dla języka, który był w pełni kompletny z rekurencją i nie zajął 10 000 wierszy.
Jonathan
5
(spojrzał na to teraz, było to około 2700 linii)
Jonathan
4
Należy pobrać i skonfigurować, make menuconfigaby zobaczyć, ile kodu można włączyć / wyłączyć przed budowaniem.
casey
6
@JonathanLeaders: Zrobiłem testowanie kompletnych kompilatorów dla języków podobnych do LISP w mniej niż 100 liniach, z programami testowymi wyświetlającymi Mandelbrots. Zawsze zależy.
fresnel

Odpowiedzi:

43

Sterowniki są utrzymywane w jądrze, więc gdy zmiana jądra wymaga globalnego wyszukiwania i zamiany (lub wyszukiwania i modyfikacji ręki) dla wszystkich użytkowników funkcji, robi to osoba dokonująca zmiany. Aktualizowanie sterownika przez osoby dokonujące zmian w interfejsie API to bardzo miła zaleta, zamiast konieczności robienia tego samemu, gdy nie kompiluje się na nowszym jądrze.

Alternatywą (co dzieje się w przypadku sterowników utrzymywanych poza drzewem) jest to, że łatka musi zostać ponownie zsynchronizowana przez swoich opiekunów, aby nadążać za wszelkimi zmianami.

Szybkie wyszukiwanie wywołało debatę na temat rozwoju sterowników wewnątrz drzewa i poza drzewem .

Linux jest obsługiwany głównie przez utrzymywanie wszystkiego w głównym repozytorium. Budowanie małych, zredukowanych jąder jest obsługiwane przez opcje konfiguracji do kontrolowania #ifdefs. Możesz więc absolutnie zbudować małe, zredukowane jądra, które kompilują tylko niewielką część kodu w całym repozytorium.

Szerokie zastosowanie Linuksa w systemach osadzonych doprowadziło do lepszego wsparcia dla pomijania rzeczy niż Linux miał wiele lat wcześniej, gdy drzewo źródeł jądra było mniejsze. Super-minimalne jądro 4.0 jest prawdopodobnie mniejsze niż super-minimalne jądro 2.4.0.

Peter Cordes
źródło
4
Teraz TO ma dla mnie sens, dlaczego logiczne jest posiadanie całego kodu razem, oszczędza roboczogodziny kosztem zasobów komputerowych i nadmiernych zależności.
Jonathan
8
@JonathanLeaders: tak, unika się zgnilizny w przypadku sterowników z mało aktywną konserwacją. Prawdopodobnie przydaje się także mieć cały kod sterownika przy rozważaniu podstawowych zmian. Wyszukiwanie wszystkich osób wywołujących niektóre wewnętrzne interfejsy API może spowodować, że sterownik użyje go w sposób, o którym nie pomyślałeś, potencjalnie wpływając na zmianę, o której myślisz.
Peter Cordes,
1
@JathanathanLeaders pojawiają się na xd, jakby te dodatkowe linie zajmowały dużo więcej miejsca we współczesnych pomiarach instalacji na komputerze.
Junaga
3
@Junaga: zdajesz sobie sprawę, że Linux jest bardzo przenośny i skalowalny, prawda? Marnowanie 1 MB stale używanej pamięci jądra na 32-MB wbudowany system to wielka sprawa. Rozmiar kodu źródłowego nie jest ważny, ale skompilowany rozmiar binarny jest nadal ważny. Pamięć jądra nie jest stronicowana, więc nawet przy wymianie przestrzeni wymiany nie można jej odzyskać.
Peter Cordes
1
@Rolf: Jest duży, ale to nie spaghetti. Obecnie jest dość dobrze zaprojektowany bez dwukierunkowych zależności między kodem podstawowym a sterownikami. Sterowniki można pominąć bez uszkodzenia jądra. Gdy funkcja wewnętrzna lub interfejs API są refaktoryzowane, więc sterowniki muszą używać go w inny sposób, sterowniki mogą wymagać zmiany, ale jest to normalne w przypadku refaktoryzacji.
Peter Cordes
79

Według cloc działającego na 3.13, Linux zawiera około 12 milionów linii kodu.

  • 7 milionów LOC w sterownikach /
  • 2 miliony LOC w łuku /
  • tylko 139 tysięcy LOC w jądrze /

lsmod | wc na moim laptopie Debian pokazuje 158 modułów załadowanych w czasie wykonywania, więc dynamiczne ładowanie modułów jest dobrze używanym sposobem wspierania sprzętu.

Solidny system konfiguracji (np. make menuconfig) Służy do wyboru, który kod ma zostać skompilowany (a bardziej do twojego punktu, którego kodu nie skompilować). Systemy osadzone definiują własny .configplik tylko za pomocą obsługiwanego sprzętu (w tym obsługi sprzętu wbudowanego w jądro lub jako moduły ładowalne).

drewbenn
źródło
2
find /lib/modules/$(uname -r)/ -name '*.ko' | wcmówi nieco ponad 3000. I FWIW, to Debian , „uniwersalny system operacyjny”, który zapewnia pełny system operacyjny, który powinien działać na każdym nowoczesnym komputerze zbudowanym wokół jądra Linux.
drewbenn
3
zliczanie modułów to za mało, być może wiele jest wbudowanych przez config
Alex,
5
Myślę, że z tego możemy wywnioskować, że jądro Linuksa jest ogromne, ponieważ obsługuje wszystkie rodzaje konfiguracji urządzeń, a nie dlatego, że jest skandalicznie złożone. Widzimy tutaj, że bardzo niewiele z 15-metrowych linii jest faktycznie używanych. Chociaż, jak prawie wszystkie rzeczy, może być zbyt skomplikowane, przynajmniej możemy spać w nocy, wiedząc, że jest to uzasadnione
Jonathan
2
@JonathanLeaders: Tak - podobnie jak moduły do ​​dziwnych urządzeń, istnieją moduły do ​​niejasnych systemów plików, protokołów sieciowych itp.
psmears,
6
@JathanathanLeader Pamiętam, kiedy zaczynał się Linux - nawet uruchomienie instalatora (nawet jeśli miał on instalatora!) Było ogromnym bólem - wciąż istnieją pewne zakłócenia, w których trzeba ręcznie wybrać sterownik myszy . Robienie takich rzeczy, jak praca w sieci lub, Boże, X-Window, praca, było rytuałem przejścia. Podczas mojej pierwszej instalacji Red Hat musiałem napisać własny sterownik karty graficznej, ponieważ były dostępne tylko trzy (!) Sterowniki. Domyślnie podstawowa praca jest oznaką dojrzałości - i oczywiście możesz sobie pozwolić na znacznie więcej ulepszeń w systemie osadzonym, w którym jest tylko kilka kombinacji sprzętowych.
Luaan,
67

Dla każdego, kto jest ciekawy, oto podział liczby wierszy dla lustra GitHub:

=============================================
    Item           Lines             %
=============================================
  ./usr                 845        0.0042
  ./init              5,739        0.0283
  ./samples           8,758        0.0432
  ./ipc               8,926        0.0440
  ./virt             10,701        0.0527
  ./block            37,845        0.1865
  ./security         74,844        0.3688
  ./crypto           90,327        0.4451
  ./scripts          91,474        0.4507
  ./lib             109,466        0.5394
  ./mm              110,035        0.5422
  ./firmware        129,084        0.6361
  ./tools           232,123        1.1438
  ./kernel          246,369        1.2140
  ./Documentation   569,944        2.8085
  ./include         715,349        3.5250
  ./sound           886,892        4.3703
  ./net             899,167        4.4307
  ./fs            1,179,220        5.8107
  ./arch          3,398,176       16.7449
  ./drivers      11,488,536       56.6110
=============================================

driversprzyczynia się do dużej liczby linii.

użytkownik3276552
źródło
19
To interesujące. Jeszcze bardziej interesujące są potencjalnie słabe punkty w kodzie, w których denerwowali się programiści:grep -Pir "\x66\x75\x63\x6b" /usr/src/linux/ | wc -l
jimmij 17'15
4
@jimmij '\ x73 \ x68 \ x69 \ x74' może być bardziej powszechny zgodnie z tymi przełomowymi (jeśli nieco przestarzałymi) badaniami .
Nick T
3
Przypadkowy fakt: folder, który jest bliższy 600 000 LOC oszacowanym przez PO, to dokumentacja.
Davidmh,
1
./documentationma ponad 500 000 linii kodu? ....co?
C_B,
2
@C_B @Davidmh Myślę, że to prosta wcliczba, która ma tę zaletę, że jest łatwiejsza do zdefiniowania niż „linie kodu” :)
Drawbenn
43

Dotychczasowe odpowiedzi wydają się brzmiać „tak, jest dużo kodu” i nikt nie odpowiada na pytanie z najbardziej logiczną odpowiedzią: 15 mln +? WIĘC CO? Co 15 mln wierszy kodu źródłowego ma wspólnego z ceną ryb? Co czyni to tak niewyobrażalnym?

Linux wyraźnie robi wiele. O wiele więcej niż cokolwiek innego ... Ale niektóre z twoich punktów pokazują, że nie szanujesz tego, co się dzieje, gdy jest zbudowany i używany.

  • Nie wszystko jest skompilowane. System kompilacji jądra umożliwia szybkie definiowanie konfiguracji, które wybierają zestawy kodu źródłowego. Niektóre są eksperymentalne, niektóre stare, niektóre po prostu nie są potrzebne dla każdego systemu. Spójrz na /boot/config-$(uname -r)(na Ubuntu) w, make menuconfiga zobaczysz, ile jest wykluczone.

    I to jest dystrybucja pulpitu ze zmiennym celem. Konfiguracja dla systemu osadzonego pobierałaby tylko to, czego potrzebuje.

  • Nie wszystko jest wbudowane. W mojej konfiguracji większość funkcji jądra jest zbudowana jako moduły:

    grep -c '=m' /boot/config-`uname -r`  # 4078
    grep -c '=y' /boot/config-`uname -r`  # 1944
    

    Żeby było jasne, można je wszystkie wbudować ... Tak jak można je wydrukować i przekształcić w gigantyczną papierową kanapkę. To po prostu nie miałoby sensu, gdybyś nie robił niestandardowej kompilacji dla dyskretnego zadania sprzętowego (w takim przypadku ograniczyłbyś już liczbę tych elementów).

  • Moduły ładowane są dynamicznie. Nawet jeśli w systemie są dostępne tysiące modułów, system pozwoli Ci załadować tylko to, czego potrzebujesz. Porównaj wyniki:

    find /lib/modules/$(uname -r)/ -iname '*.ko' | wc -l  # 4291
    lsmod | wc -l                                         # 99
    

    Prawie nic nie jest załadowane.

  • Mikrojądra to nie to samo. Wystarczy 10 sekund, by spojrzeć na wiodący obraz do strony Wikipedii, do której się odnosiłeś , podkreślając, że są one zaprojektowane w zupełnie inny sposób.

    Sterowniki systemu Linux są zinternalizowane (głównie jako moduły ładowane dynamicznie), a nie przestrzeń użytkownika, a systemy plików są podobnie wewnętrzne. Dlaczego jest to gorsze niż używanie zewnętrznych sterowników? Dlaczego mikro jest lepsze do obliczeń ogólnego zastosowania?


Komentarze ponownie podkreślają, że go nie otrzymujesz. Jeśli chcesz wdrożyć Linuksa na dyskretnym sprzęcie (np. Lotniczym, TiVo, tablecie itp.) , Skonfiguruj go tak, aby budował tylko potrzebne sterowniki . Możesz zrobić to samo na pulpicie za pomocą make localmodconfig. W efekcie powstaje niewielka, specjalnie zaprojektowana wersja jądra z zerową elastycznością.

W przypadku dystrybucji takich jak Ubuntu dopuszczalny jest pojedynczy pakiet jądra o wielkości 40 MB. Nie, wyczyść to, w rzeczywistości jest to lepsze niż masowe archiwizowanie i pobieranie scenariusza, w którym utrzymywanie ponad 4000 pływających modułów w postaci pakietów. Zużywa dla nich mniej miejsca na dysku, łatwiejsze do spakowania w czasie kompilacji, łatwiejsze do przechowywania i jest lepszy dla ich użytkowników (którzy mają system, który po prostu działa).

Przyszłość też nie wydaje się problemem. Szybkość procesora, gęstość dysku / ceny i poprawa przepustowości wydają się znacznie szybsze niż wzrost jądra. Pakiet 200 MB jądra za 10 lat nie byłby końcem, gdyby świat.

To też nie jest ulica jednokierunkowa. Kod zostaje wyrzucony, jeśli nie jest utrzymywany.

Oli
źródło
2
Dotyczy to głównie systemów wbudowanych. Jak widać, masz 4000 modułów, które nie są używane w twoim systemie. W niektórych małych zastosowaniach robotyki lub lotnictwa (CZYTAJ: nie do obliczeń ogólnego przeznaczenia) byłoby to nie do przyjęcia.
Jonathan
2
@JathanathanLeaders Myślę, że możesz je bezpiecznie usunąć. Są instalowane na komputerze stacjonarnym, na wypadek gdybyś nagle podłączył coś do portu USB lub zmienił konfigurację sprzętu itp.
Didier A.,
1
Tak, dokładnie. Nadal jestem zaskoczony założeniami typu „możesz podłączyć urządzenie USB w dowolnym momencie, dlatego potrzebujemy 15 milionów linii kodu” zapisanych na poziomie jądra , a nie na poziomie dystrybucji, ponieważ Linux jest używany w telefonie i różnych urządzenia osadzone. Cóż, myślę, że dystrybucja sama usuwa listę. Po prostu uważam, że wsparcie dla wtykowalności powinno być addytywne, a nie subtraktywne, tzn. Dystrybucja w pewnym sensie „opt-in” do niego poprzez dodanie źródeł pakietów, w przeciwieństwie do wbudowanych konfiguracji ARM mówiących, że jądro ma jeden procent jego obecnej wielkości
Jonathan
5
@JathanathanLeaders nigdy nie uruchomiłbyś jądra skonfigurowanego dla komputera stacjonarnego w systemie osadzonym. Nasz system wbudowany ma 13 modułów i usunął całą pomoc sprzętową, której nie potrzebujemy (wraz z wieloma innymi dostosowaniami). Przestań porównywać komputery stacjonarne z systemami osadzonymi. Linux działa dobrze, ponieważ obsługuje wszystko i można go dostosować tak, aby zawierał tylko to, na czym Ci zależy. Te moduły 4k są naprawdę świetne na komputerach stacjonarnych: kiedy mój ostatni laptop zmarł, po prostu włożyłem dysk twardy do znacznie nowszego laptopa i wszystko po prostu działało .
drewbenn
3
Ta skądinąd dobra / cenna odpowiedź ma wyraźnie zły i bojowy ton. -1.
TypeIA
19

Liczba wierszy skompilowanych przez Linux tinyconfig Tinyconfig Bubble Graph SVG (skrzypce)

skrypt powłoki, aby utworzyć Json z kompilacji jądra, użyj z http://bl.ocks.org/mbostock/4063269


Edycja : okazało się, unifdefże ma pewne ograniczenia ( -Ijest ignorowane i -includenieobsługiwane, ten drugi służy do dołączenia wygenerowanego nagłówka konfiguracji) w tym momencie użycie catnie zmienia wiele:

274692 total # (was 274686)

skrypt i procedura zostały zaktualizowane.


Oprócz sterowników, arch itp. Jest wiele skompilowanych kodów warunkowych lub nie, w zależności od wybranej konfiguracji, kod niekoniecznie w dynamicznie ładowanych modułach, ale wbudowany w rdzeń.

Tak więc, pobrałem źródła linux-4.1.6 , wybrałem tinyconfig , nie włącza modułów i szczerze mówiąc nie wiem, co to włącza ani co użytkownik może z tym zrobić w czasie wykonywania, w każdym razie skonfiguruj jądro:

# tinyconfig      - Configure the tiniest possible kernel
make tinyconfig

zbudował jądro

time make V=1 # (should be fast)
#1049168 ./vmlinux (I'm using x86-32 on other arch the size may be different)

proces kompilacji jądra pozostawia ukryte pliki wywoływane *.cmdza pomocą wiersza poleceń używanego również do kompilacji .oplików, przetwarzania tych plików i wyodrębnienia kopii celu i zależności script.shponiżej i użycia jej z find :

find -name "*.cmd" -exec sh script.sh "{}" \;

tworzy to kopię dla każdej zależności o .onazwie o nazwie cel.o.c

kod .c

find -name "*.o.c" | grep -v "/scripts/" | xargs wc -l | sort -n
...
   8285 ./kernel/sched/fair.o.c
   8381 ./kernel/sched/core.o.c
   9083 ./kernel/events/core.o.c
 274692 total

.h nagłówki (odkażone)

make headers_install INSTALL_HDR_PATH=/tmp/test-hdr
find /tmp/test-hdr/ -name "*.h" | xargs wc -l
...
  1401 /tmp/test-hdr/include/linux/ethtool.h
  2195 /tmp/test-hdr/include/linux/videodev2.h
  4588 /tmp/test-hdr/include/linux/nl80211.h
112445 total
Alex
źródło
@JathanathanLeaders bawił się nad tym, ciesząc się, że ktoś to lubi
Alex
9

Kompromisy dotyczące monolitycznych jąder były od samego początku dyskutowane publicznie między Tananbaumem i Torvaldsem. Jeśli nie musisz wchodzić do przestrzeni użytkownika, wszystko w interfejsie jądra może być prostsze. Jeśli jądro jest monolityczne, może być wewnętrznie bardziej zoptymalizowane (i bardziej niechlujne!).

Od dłuższego czasu mieliśmy moduły jako kompromis. I kontynuuje takie rzeczy jak DPDK (przenoszenie większej liczby funkcji sieciowych z jądra). Im więcej rdzeni zostanie dodanych, tym ważniejsze jest unikanie blokowania; więc więcej rzeczy przeniesie się do przestrzeni użytkownika, a jądro się skurczy.

Zauważ, że monolityczne jądra nie są jedynym rozwiązaniem. W niektórych architekturach granica jądra / przestrzeni użytkownika nie jest droższa niż jakiekolwiek inne wywołanie funkcji, co czyni mikrokernele atrakcyjnymi.

Obrabować
źródło
1
„W niektórych architekturach granica jądra / przestrzeni użytkownika nie jest droższa niż jakiekolwiek inne wywołanie funkcji” - ciekawe! Jaka to byłaby architektura? Wygląda niesamowicie ciężko, jeśli nie tylko porzucisz jakąkolwiek ochronę pamięci.
Voo,
1
Przejrzałem wszystkie filmy millcomputing.com Iwana Goddarda (procesor młyn / pasek, bardzo podobny do VLIW). To szczególne twierdzenie jest centralnym tematem, a jego implikacje nie są oczywiste, dopóki nie przejdziesz do wideo bezpieczeństwa. Jest to architektura POC w symulacji, ale prawdopodobnie nie jest to jedyna architektura z tą właściwością.
Rob
1
Ach, to wyjaśnia. Z mojego doświadczenia (i jako pierwszy przyznam, że nie podążam tak ściśle za branżą), istnieje wiele symulowanych architektur i niewiele z nich spełnia swoje roszczenia, gdy tylko guma trafi na drogę, tj. Są one wprowadzone na prawdziwym sprzęcie. Chociaż pomysł, który się za tym kryje, może być w każdym razie interesujący - nie po raz pierwszy wspomniany konkretny procesor. Jeśli kiedykolwiek znajdziesz istniejącą architekturę, która ma tę właściwość, byłbym bardzo zainteresowany.
Voo,
1
BTW, oto więcej zasobów na temat wspomnianej debaty: en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Jonathan