Warum enthält der Linux-Kernel mehr als 15 Millionen Codezeilen? [geschlossen]

109

Was ist der Inhalt dieser monolithischen Codebasis?

Ich verstehe die Unterstützung der Prozessorarchitektur, die Sicherheit und die Virtualisierung, kann mir aber nicht vorstellen, dass das mehr als 600.000 Zeilen sind.

Was sind die historischen und aktuellen Gründe, warum Treiber in der Kernel-Codebasis enthalten sind?

Enthalten diese mehr als 15 Millionen Leitungen jeden einzelnen Treiber für jede Hardware? Wenn ja, stellt sich dann die Frage, warum Treiber in den Kernel eingebettet sind und nicht Pakete, die automatisch erkannt und von Hardware-IDs installiert werden?

Ist die Größe der Codebasis ein Problem für Geräte mit eingeschränktem Speicher oder mit eingeschränktem Speicher?

Es scheint, als würde die Kernelgröße für ARM-Geräte mit eingeschränktem Speicherplatz aufgebläht, wenn alles eingebettet wäre. Werden viele Zeilen vom Präprozessor ausgesondert? Nennen Sie mich verrückt, aber ich kann mir nicht vorstellen, dass eine Maschine so viel Logik benötigt, um zu funktionieren. Ich verstehe, dass es sich um die Rollen eines Kernels handelt.

Gibt es Beweise dafür, dass die Größe in mehr als 50 Jahren ein Problem sein wird, da sie anscheinend immer größer wird?

Das Einbeziehen von Treibern bedeutet, dass es mit der Hardware wächst.

EDIT : Für diejenigen, die denken, dass dies die Natur des Kernels ist, wurde mir nach einigen Recherchen klar, dass dies nicht immer der Fall ist. Ein Kernel muss nicht so groß sein, da der Microkernel Mach von Carnegie Mellon als Beispiel aufgeführt wurde: "Normalerweise weniger als 10.000 Codezeilen".

Jonathan
quelle
9
Im Jahr 2012 gab es mehr als 5 Millionen Leitungen nur für Fahrer. 1,9 Millionen Leitungen zur Unterstützung verschiedener Prozessorarchitekturen. Mehr Infos h-online.com/open/features/...
steve
11
Ja, ich habe einen Compiler, einen lexikalischen Analysator und einen Bytecode-Generator für eine Sprache codiert. Die Rekursion war vollständig und es wurden keine 10.000 Zeilen benötigt.
Jonathan
5
(sah es jetzt an, es waren ungefähr 2.700 Zeilen)
Jonathan
4
Sie sollten herunterladen und konfigurieren , make menuconfigum zu sehen , wie viel von dem Code kann aktiviert / deaktiviert , um Gebäude vor werden.
Casey
6
@JonathanLeaders: Ich habe komplette Compiler für LISP-ähnliche Sprachen in weniger als 100 Zeilen erstellt, mit Testprogrammen, die Mandelbrots rendern. Kommt immer drauf an.
Phresnel

Antworten:

43

Treiber werden im Kernel verwaltet. Wenn eine Kerneländerung ein globales Suchen und Ersetzen (oder Suchen und Ändern von Hand) für alle Benutzer einer Funktion erfordert, wird dies von der Person durchgeführt, die die Änderung vornimmt. Das Aktualisieren Ihres Treibers durch Benutzer, die API-Änderungen vornehmen, ist ein sehr schöner Vorteil, anstatt dies selbst tun zu müssen, wenn es auf einem neueren Kernel nicht kompiliert werden kann.

Die Alternative (was bei Treibern geschieht, die außerhalb der Baumstruktur gepflegt werden) besteht darin, dass der Patch von den Betreuern erneut synchronisiert werden muss, um mit den Änderungen Schritt zu halten.

Eine schnelle Suche führte zu einer Debatte über die Entwicklung von In-Tree- und Out-of-Tree- Treibern.

Die Art und Weise, wie Linux gewartet wird, besteht hauptsächlich darin, alles im Mainline-Repo zu belassen. Das Erstellen kleiner, reduzierter Kernel wird durch Konfigurationsoptionen zur Steuerung von #ifdefs unterstützt. Sie können also absolut winzige, abgespeckte Kernel erstellen, die im gesamten Repo nur einen winzigen Teil des Codes kompilieren.

Die umfangreiche Verwendung von Linux in eingebetteten Systemen hat zu einer besseren Unterstützung für das Weglassen von Dingen geführt, als Linux dies Jahre zuvor getan hatte, als der Kernel-Quellbaum kleiner war. Ein Super-Minimal-4.0-Kernel ist wahrscheinlich kleiner als ein Super-Minimal-2.4.0-Kernel.

Peter Cordes
quelle
4
Jetzt macht mir DAS Sinn, warum es logisch ist, den gesamten Code zusammen zu haben. Es spart Arbeitsstunden auf Kosten von Computerressourcen und übermäßigen Abhängigkeiten.
Jonathan
8
@ JonathanLeaders: Ja, es vermeidet Bit-Rot für Fahrer mit nicht sehr aktiver Wartung. Es ist wahrscheinlich auch nützlich, den gesamten Treibercode zur Verfügung zu haben, wenn Kernänderungen in Betracht gezogen werden. Das Durchsuchen aller Aufrufer einer internen API kann dazu führen, dass ein Treiber diese auf eine Weise verwendet, an die Sie nicht gedacht haben, und möglicherweise eine Änderung beeinflusst, über die Sie nachgedacht haben.
Peter Cordes
1
@ JonathanLeaders kommen auf xd, als ob diese zusätzlichen Zeilen viel mehr Platz in Anspruch nehmen, in modernen Messungen der Installation auf einem PC.
Junaga
3
@Junaga: Dir ist klar, dass Linux sehr portabel und skalierbar ist, oder? Es ist eine große Sache, 1 MB permanent verwendeten Kernel-Speicher auf einem 32-MB-Embedded-System zu verschwenden. Die Größe des Quellcodes ist nicht wichtig, aber die kompilierte Binärgröße ist weiterhin wichtig. Der Kernel-Speicher wird nicht ausgelagert, sodass Sie ihn selbst bei Swap-Speicher nicht zurückerhalten können.
Peter Cordes
1
@Rolf: Es ist groß, aber es ist kein Spaghetti. Derzeit ist die Architektur ohne wechselseitige Abhängigkeiten zwischen Kerncode und Treibern recht gut. Treiber können weggelassen werden, ohne den Kernel zu beschädigen. Wenn eine interne Funktion oder API umgestaltet wird, sodass Treiber sie anders verwenden müssen, müssen Treiber möglicherweise geändert werden. Dies ist jedoch beim Umgestalten normal.
Peter Cordes
79

Laut Cloc Run gegen 3.13 besteht Linux aus etwa 12 Millionen Codezeilen.

  • 7 Millionen LOC in Fahrern /
  • 2 Millionen LOC in Bogen /
  • nur 139 Tausend LOC im Kernel /

lsmod | wc Auf meinem Debian-Laptop werden 158 Module zur Laufzeit geladen, so dass das dynamische Laden von Modulen eine häufig verwendete Methode zur Unterstützung von Hardware ist.

Das robuste Konfigurationssystem (z. B. make menuconfig) wird verwendet, um auszuwählen, welcher Code kompiliert werden soll (und mehr zu Ihrem Punkt, welcher Code nicht kompiliert werden soll). Eingebettete Systeme definieren ihre eigene .configDatei mit der Hardware-Unterstützung, die ihnen wichtig ist (einschließlich der Unterstützung der im Kernel integrierten Hardware oder als ladbare Module).

Drewbenn
quelle
3
Das Zählen von Modulen ist nicht genug, eine Menge wird vielleicht von Config eingebaut
Alex
5
Ich denke, wir können daraus schließen, dass der Linux-Kernel massiv ist, weil er alle Arten von Gerätekonfigurationen unterstützt, nicht weil er unglaublich komplex ist. Wir sehen hier, dass nur sehr wenige der 15 m langen Leitungen tatsächlich benutzt werden. Obwohl fast alles zu komplex sein mag, können wir zumindest nachts schlafen, wenn wir wissen, dass es in Ordnung ist
Jonathan
2
@JonathanLeaders: Ja - und neben Modulen für fremde Geräte gibt es Module für obskure Dateisysteme, Netzwerkprotokolle usw.
psmears
6
@JonathanLeader Ich erinnere mich , als Linux begann - auch immer das Installationsprogramm zu arbeiten (wenn es auch einen Installer hat!) War ein massiver Schmerz - es gibt immer noch einige Distributionen , wo Sie Ihren holen müsst Maustreiber manuell. Dinge wie Networking oder, Gott bewahre, X-Window zum Funktionieren zu bringen, war ein Übergangsritus. Bei meiner ersten Red Hat-Installation musste ich meinen eigenen Grafiktreiber schreiben, da nur drei (!) Treiber verfügbar waren. Das standardmäßige Arbeiten mit Grundlagen ist ein Zeichen der Reife - und natürlich können Sie es sich leisten, in einem eingebetteten System, in dem es nur wenige HW-Kombinationen gibt, viel mehr Änderungen vorzunehmen.
Luaan
2
@ JonathanLeaders Wie ich glaube, ist der LOC in der Quelle mehr oder weniger irrelevant. Wenn Sie wissen möchten, wie viel Speicher der Kernel verwendet, gibt es viel direktere Möglichkeiten .
Goldlöckchen
67

Für alle, die neugierig sind, hier ist die Aufschlüsselung der Zeilenanzahl für den GitHub-Spiegel:

=============================================
    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
=============================================

driversträgt zu einem Großteil der Zeilenanzahl bei.

user3276552
quelle
19
Das ist interessant. Noch interessanter sind potenzielle Schwachstellen im Code, über die sich die Programmierer geärgert haben:grep -Pir "\x66\x75\x63\x6b" /usr/src/linux/ | wc -l
jimmij
4
@jimmij '\ x73 \ x68 \ x69 \ x74' ist laut dieser bahnbrechenden (wenn auch etwas veralteten) Studie möglicherweise häufiger anzutreffen .
Nick T
3
Zufällige Tatsache: Der Ordner, der näher an der vom OP geschätzten 600 000 LOC liegt, ist die Dokumentation.
Davidmh
1
./documentationhat über 500.000 Codezeilen? ....Was?
C_B
1
@drewbenn Ich verstand es eher als "Dokumentation ist nicht leer?"
Izkata
43

Die bisherigen Antworten scheinen zu lauten "Ja, es gibt viel Code" und niemand geht die Frage mit der logischsten Antwort an: 15 Millionen +? NA UND? Was haben 15 Millionen Zeilen Quellcode mit dem Preis für Fisch zu tun? Was macht das so unvorstellbar?

Linux leistet eindeutig viel. Viel mehr als alles andere ... Aber einige deiner Punkte zeigen, dass du nicht respektierst, was passiert, wenn es gebaut und benutzt wird.

  • Nicht alles ist kompiliert. Mit dem Kernel-Build-System können Sie schnell Konfigurationen definieren, die Sätze von Quellcode auswählen. Manche sind experimentell, manche sind alt, manche werden einfach nicht für jedes System benötigt. Schauen Sie sich /boot/config-$(uname -r)(auf Ubuntu) in an make menuconfigund Sie werden sehen, wie viel davon ausgeschlossen ist.

    Und das ist eine Desktop-Distribution mit variablem Ziel. Die Konfiguration für ein eingebettetes System würde nur die Dinge einbeziehen, die es benötigt.

  • Nicht alles ist eingebaut. In meiner Konfiguration sind die meisten Kernel-Funktionen als Module aufgebaut:

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

    Um es klar zu sagen, diese könnten alle eingebaut sein ... Genau wie sie ausgedruckt und zu einem riesigen Papiersandwich verarbeitet werden könnten. Es wäre nur sinnvoll, wenn Sie einen benutzerdefinierten Build für einen diskreten Hardware-Job ausführen würden (in diesem Fall hätten Sie die Anzahl dieser Elemente bereits begrenzt).

  • Module werden dynamisch geladen. Selbst wenn einem System Tausende von Modulen zur Verfügung stehen, können Sie mit dem System genau das laden, was Sie benötigen. Vergleichen Sie die Ausgaben von:

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

    Es ist fast nichts geladen.

  • Mikrokerne sind nicht dasselbe. Wenn Sie das führende Bild der von Ihnen verlinkten Wikipedia-Seite in nur 10 Sekunden betrachten, wird deutlich, dass sie auf eine völlig andere Art und Weise gestaltet sind.

    Linux-Treiber sind internalisiert (meist als dynamisch geladene Module), nicht als Userspace, und die Dateisysteme sind ähnlich intern. Warum ist das schlimmer als mit externen Treibern? Warum ist Mikro besser für Allzweck-Computing?


Die Kommentare heben erneut hervor, dass Sie es nicht verstehen. Wenn Sie Linux auf diskreter Hardware (z. B. Luft- und Raumfahrt, TiVo, Tablet usw.) bereitstellen möchten, konfigurieren Sie es so, dass nur die benötigten Treiber erstellt werden . Sie können dasselbe auf Ihrem Desktop mit tun make localmodconfig. Am Ende haben Sie einen winzigen zweckgebundenen Kernel-Build ohne Flexibilität.

Für Distributionen wie Ubuntu ist ein einzelnes 40-MB-Kernel-Paket akzeptabel. Nein, das ist besser als das massive Archivierungs- und Download-Szenario, bei dem 4000+ Floating-Module als Pakete erhalten bleiben. Es benötigt weniger Speicherplatz für sie, ist einfacher beim Kompilieren zu packen, einfacher zu speichern und ist besser für ihre Benutzer (die ein System haben, das einfach funktioniert).

Auch die Zukunft scheint kein Thema zu sein. Die Geschwindigkeit der CPU-Geschwindigkeit, der Festplattendichte / Preisgestaltung und der Bandbreitenverbesserungen scheint viel schneller zu sein als das Wachstum des Kernels. Ein 200MB Kernel-Paket in 10 Jahren wäre nicht das Ende der Welt.

Es ist auch keine Einbahnstraße. Code wird rausgeschmissen, wenn er nicht gepflegt wird.

Oli
quelle
2
Das Problem betrifft hauptsächlich eingebettete Systeme. Wie Sie sehen, sind auf Ihrem eigenen System 4.000 Module nicht in Verwendung. In einigen kleinen Robotik- oder Luftfahrtanwendungen (READ: not general purpose computing) wäre dies inakzeptabler Abfall.
Jonathan
2
@ JonathanLeaders Ich denke, Sie können sie sicher löschen. Bei einer Desktop-Installation sind sie für den Fall vorhanden, dass Sie plötzlich etwas an einen USB-Port anschließen oder eine Hardwarekonfiguration ändern.
Didier A.
1
Ja genau. Ich bin immer noch überrascht von Annahmen wie "Sie könnten ein USB-Gerät jederzeit anschließen, daher benötigen wir 15 Millionen Codezeilen", die auf Kernel- Ebene und nicht auf Distributionsebene geschrieben sind, da Linux in Telefonen und verschiedenen Betriebssystemen verwendet wird eingebettete Geräte. Nun, ich denke , die Distro hat die Liste keulen auf seine eigenen. Ich würde denken Sie nur Unterstützung für Steckbarkeit additiv sein sollte und nicht subtraktiven, IE eine Distro würde Art ‚Opt-in‘ , um es von Paketquellen hinzugefügt, wie Embedded - ARM - Konfigurationen zu sagen , den Kernel gegen ein Prozent zu sein , es aktuelle Größe ist
Jonathan
5
@JonathanLeaders Sie würden niemals einen Kernel ausführen , der für einen Desktop auf einem eingebetteten System konfiguriert ist. Unsere Embedded - System hat 13 Module und entfernt alle Hardware - Unterstützung brauchen wir nicht (zusammen mit vielen anderen Anpassungen). Beenden Sie den Vergleich von Desktops mit eingebetteten Systemen. Linux funktioniert gut, weil es alles unterstützt und so angepasst werden kann, dass nur das enthalten ist, was Sie interessiert. Und diese 4k-Module sind wirklich großartig auf Desktop-Systemen: Als mein letzter Laptop starb, habe ich die Festplatte in einen viel neueren Laptop gesteckt und alles hat einfach funktioniert .
Drewbenn
3
Diese ansonsten gute / wertvolle Antwort leidet unter einem deutlich wütenden und kämpferischen Ton. -1.
TypeIA
19

Linux tinyconfig kompilierte die Zeilenanzahl der Quellen tinyconfig bubble graph svg (Geige)

Shell-Skript zum Erstellen des JSON aus dem Kernel-Build unter http://bl.ocks.org/mbostock/4063269


Bearbeiten : stellte sich heraus , unifdefhaben einige Einschränkungen ( -Iwird ignoriert und -includenicht unterstützte, letztere verwendet wird , um die erzeugte Konfigurations - Header enthalten) an dieser Stelle mit catändert sich nicht viel:

274692 total # (was 274686)

Skript und Prozedur aktualisiert.


Neben Treibern, Arch usw. gibt es eine Menge Bedingungscode, der kompiliert oder nicht kompiliert wird, abhängig von der gewählten Konfiguration. Code muss nicht unbedingt in dynamisch geladenen Modulen, sondern im Kern integriert sein.

Also, Linux-4.1.6-Quellen heruntergeladen , tinyconfig ausgewählt , Module nicht aktiviert und ich weiß ehrlich gesagt nicht, was es aktiviert oder was ein Benutzer zur Laufzeit damit machen kann, jedenfalls den Kernel konfigurieren:

# tinyconfig      - Configure the tiniest possible kernel
make tinyconfig

baute den Kernel

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

Der Kernel-Erstellungsprozess lässt versteckte Dateien *.cmdmit der Kommandozeile aufgerufen , die auch zum Erstellen von .oDateien verwendet wird, um diese Dateien zu verarbeiten und Ziel- und Abhängigkeiten zu extrahieren. Kopieren Sie die folgenden Dateien script.shund verwenden Sie sie mit find :

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

Dadurch wird eine Kopie für jede Abhängigkeit des .obenannten Ziels erstellt.o.c

.c Code

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 Header ( bereinigt )

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
quelle
@ JonathanLeaders Spaß daran zu arbeiten, froh, dass es jemand mag
Alex
9

Die Kompromisse zwischen monolithischen Kernen wurden von Anfang an öffentlich zwischen Tananbaum und Torvalds diskutiert. Wenn Sie nicht für alles in den Userspace wechseln müssen, ist die Schnittstelle zum Kernel möglicherweise einfacher. Wenn der Kernel monolithisch ist, kann er intern optimiert (und unordentlicher!) Werden.

Wir haben schon seit einiger Zeit Module als Kompromiss. Und es geht weiter mit Dingen wie DPDK (Verschieben von mehr Netzwerkfunktionalität aus dem Kernel). Je mehr Kerne hinzugefügt werden, desto wichtiger ist es, ein Blockieren zu vermeiden. So rücken mehr Dinge in den Benutzerbereich und der Kernel wird kleiner.

Beachten Sie, dass monolithische Kernel nicht die einzige Lösung sind. Auf einigen Architekturen ist die Grenze zwischen Kernel und Benutzerbereich nicht teurer als jeder andere Funktionsaufruf, wodurch Mikrokerne attraktiv werden.

rauben
quelle
1
"Auf einigen Architekturen ist die Kernel / Userspace-Grenze nicht teurer als jeder andere Funktionsaufruf" - interessant! Welche Architektur wäre das? Sieht unglaublich schwierig aus, wenn Sie nicht auf irgendeinen Speicherschutz verzichten.
Voo
1
Ich habe alle Videos von Ivan Goddard auf millcomputing.com durchgesehen (mill / belt-CPU, sehr VLIW-ähnlich). Diese besondere Behauptung ist ein zentrales Thema, und ihre Auswirkungen sind erst beim Betrachten des Sicherheitsvideos ersichtlich. Es ist eine POC-Architektur in der Simulation, aber wahrscheinlich nicht die einzige Architektur mit dieser Eigenschaft.
Rob
1
Ah das erklärt es. Meiner Erfahrung nach (und ich gebe als Erster zu, dass ich die Branche nicht so genau verfolge) gibt es viele simulierte Architekturen, und nur wenige werden ihren Ansprüchen gerecht, sobald der Kautschuk auf die Straße kommt, dh wenn sie eingesetzt werden auf echter Hardware. Obwohl die Idee dahinter auf jeden Fall interessant sein könnte - nicht das erste Mal, dass diese bestimmte CPU erwähnt wurde. Wenn Sie jemals eine vorhandene Architektur finden, die diese Eigenschaft besitzt, wäre ich sehr interessiert.
Voo
1
Übrigens gibt es hier mehr Ressourcen zu der von Ihnen erwähnten Debatte: en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Jonathan