Perché il kernel Linux ha oltre 15 milioni di righe di codice? [chiuso]


109

Quali sono i contenuti di questa base di codice monolitico?

Comprendo il supporto dell'architettura del processore, la sicurezza e la virtualizzazione, ma non riesco a immaginare che si tratti di oltre 600.000 linee o giù di lì.

Quali sono i motivi storici e attuali dei driver inclusi nella base di codice del kernel?

Quei 15+ milioni di linee includono ogni singolo driver per ogni componente hardware di sempre? In tal caso, ciò pone la domanda, perché i driver sono incorporati nel kernel e non pacchetti separati che vengono rilevati automaticamente e installati dagli ID hardware?

La dimensione della base di codice è un problema per i dispositivi con limiti di memoria o di memoria?

Sembra che gonfierebbe le dimensioni del kernel per i dispositivi ARM con spazio limitato se tutto ciò fosse incorporato. Molte linee sono state selezionate dal preprocessore? Chiamami pazzo, ma non riesco a immaginare una macchina che abbia bisogno di tanta logica per eseguire ciò che capisco sono i ruoli di un kernel.

Ci sono prove che la dimensione sarà un problema in oltre 50 anni a causa della sua natura apparentemente in crescita?

Includere i driver significa che crescerà man mano che viene prodotto l'hardware.

EDIT : Per coloro che pensano che questa sia la natura dei kernel, dopo alcune ricerche ho capito che non è sempre. Non è necessario che un kernel sia così grande, poiché il microkernel Mach di Carnegie Mellon è stato elencato come esempio "di solito con meno di 10.000 righe di codice"


9
Nel 2012 aveva oltre 5 milioni di linee solo per i conducenti. 1,9 milioni di linee per supportare diverse architetture di processori. Maggiori informazioni h-online.com/open/features/…
steve

11
Sì, ho codificato un compilatore, un analizzatore lessicale e un generatore di codice byte per una lingua, e stava diventando completo più ricorsione e non ha impiegato 10.000 righe.
Jonathan,

5
(guardandolo ora, erano circa 2.700 linee)
Jonathan il

4
È necessario scaricare e configurare make menuconfigper vedere la quantità di codice che può essere abilitata / disabilitata prima della creazione.
Casey,

6
@JonathanLeaders: ho compilato compilatori completi per LISP come lingue in meno di 100 righe, con programmi di test che eseguivano il rendering di Mandelbrots. Dipende sempre.
galleria

Risposte:


43

I driver sono gestiti nel kernel, quindi quando una modifica del kernel richiede una ricerca e sostituzione globale (o ricerca e modifica a mano) per tutti gli utenti di una funzione, viene eseguita dalla persona che effettua la modifica. Far aggiornare il tuo driver da persone che apportano modifiche alle API è un bel vantaggio, invece di doverlo fare da solo quando non si compila su un kernel più recente.

L'alternativa (che è ciò che accade per i driver mantenuti fuori dall'albero), è che la patch deve essere risincronizzata dai suoi manutentori per tenere il passo con qualsiasi modifica.

Una rapida ricerca ha sollevato un dibattito sullo sviluppo di driver in-tree vs. out-of-tree .

Il modo in cui Linux viene mantenuto è principalmente mantenendo tutto nel repository mainline. La costruzione di piccoli kernel ridotti è supportata da opzioni di configurazione per controllare #ifdefs. Quindi puoi assolutamente costruire piccoli kernel eliminati che compilano solo una piccola parte del codice nell'intero repository.

L'ampio uso di Linux nei sistemi embedded ha portato a un supporto migliore per lasciare cose fuori rispetto a Linux anni prima quando l'albero dei sorgenti del kernel era più piccolo. Un kernel 4.0 super minimale è probabilmente più piccolo di un kernel 2.4.0 super minimale.


4
Ora QUESTO ha senso per me perché sia ​​logico avere tutto il codice insieme, fa risparmiare ore-uomo a scapito delle risorse del computer e delle dipendenze eccessive.
Jonathan,

8
@JonathanLeaders: sì, evita il bit-rot per i conducenti con manutenzione non molto attiva. Probabilmente è anche utile avere tutto il codice del driver in giro quando si considerano le modifiche di base. La ricerca su tutti i chiamanti di alcune API interne potrebbe far apparire un driver che lo utilizza in un modo a cui non hai pensato, influenzando potenzialmente un cambiamento a cui stavi pensando.
Peter Cordes,

1
@JonathanLeaders arriva su xd, come se quelle linee extra occupassero molto spazio extra, nelle moderne misurazioni dell'installazione su un PC.
Junaga,

3
@Junaga: ti rendi conto che Linux è molto portatile e scalabile, giusto? Sprecare 1 MB di memoria del kernel utilizzata in modo permanente su un sistema integrato da 32 MB è un grosso problema. La dimensione del codice sorgente non è importante, ma la dimensione binaria compilata è ancora importante. La memoria del kernel non è paginata, quindi anche con lo spazio di swap non è possibile recuperarla.
Peter Cordes,

1
@Rolf: è grande, ma non è spaghetti. Attualmente è abbastanza ben progettato senza dipendenze bidirezionali tra codice core e driver. I driver possono essere esclusi senza interrompere il kernel principale. Quando una funzione interna o API viene refactored, quindi i driver devono usarla in modo diverso, potrebbe essere necessario cambiare driver, ma questo è normale per il refactoring.
Peter Cordes,

79

Secondo cloc eseguito contro 3.13, Linux ha circa 12 milioni di righe di codice.

  • 7 milioni di LOC nei driver /
  • 2 milioni di LOC in arco /
  • solo 139 mila LOC nel kernel /

lsmod | wc sul mio laptop Debian mostra 158 moduli caricati in fase di runtime, quindi caricare dinamicamente i moduli è un modo ben utilizzato per supportare l'hardware.

Il robusto sistema di configurazione (ad es. make menuconfig) Viene utilizzato per selezionare quale codice compilare (e più precisamente, quale codice non compilare). I sistemi incorporati definiscono il proprio .configfile con il solo supporto hardware di loro interesse (incluso il supporto hardware incorporato nel kernel o come moduli caricabili).


3
il conteggio dei moduli non è abbastanza, forse è stato creato da config
Alex

5
Penso che da questo possiamo concludere che il kernel Linux è enorme perché supporta tutti i tipi di configurazioni del dispositivo, non perché è oltraggiosamente complesso. Vediamo qui che pochissime linee da 15 m sono effettivamente in uso. Sebbene, come quasi tutte le cose, potrebbe essere eccessivamente complesso, almeno possiamo dormire la notte sapendo che è ragionevole
Jonathan

2
@JonathanLeaders: Sì - e oltre ai moduli per strani dispositivi, ci sono moduli per oscuri filesystem, protocolli di rete, ecc ...
psmears

6
@JonathanLeader Ricordo quando Linux stava avviando - anche far funzionare l'installer (se avesse anche un installer!) È stato un grosso problema - ci sono ancora alcune distro dove devi scegliere il tuo driver del mouse manualmente. Fare cose come fare rete o, dio non voglia, X-window, lavorare, era un rito di passaggio. Alla mia prima installazione di Red Hat, ho dovuto scrivere il mio driver grafico, perché c'erano solo tre (!) Driver disponibili. Avere le nozioni di base funzionanti per impostazione predefinita è un segno di maturità - e ovviamente, puoi permetterti molte più modifiche su un sistema incorporato, dove ci sono solo poche combinazioni HW.
Luaan,

2
@JonathanLeaders Come penso tu abbia capito, il LOC nella fonte è più o meno irrilevante. Se vuoi sapere quanta memoria usa il kernel ci sono molti più modi diretti .
Riccioli d'oro,

67

Per chiunque sia curioso, ecco la suddivisione del linecount per il mirror 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
=============================================

driverscontribuisce a molto del linecount.


19
Interessante. Ancora più interessanti sono i punti potenzialmente deboli del codice, in cui i programmatori erano infastiditi:grep -Pir "\x66\x75\x63\x6b" /usr/src/linux/ | wc -l
jimmij

4
@jimmij '\ x73 \ x68 \ x69 \ x74' potrebbe essere più comune secondo questa ricerca rivoluzionaria (se leggermente datata) .
Nick T

3
Fatti casuali: la cartella più vicina ai 600.000 LOC stimati dall'OP è la documentazione.
Davidmh,

1
./documentationha oltre 500.000 righe di codice? ....che cosa?
C_B,

1
@drewbenn L'ho capito più come "la documentazione non è vuota?"
Izkata,

43

Le risposte finora sembrano essere "sì, c'è un sacco di codice" e nessuno sta affrontando la domanda con la risposta più logica: 15 M +? E ALLORA? Cosa hanno a che fare 15 milioni di righe di codice sorgente con il prezzo del pesce? Cosa lo rende così inimmaginabile?

Linux fa chiaramente molto. Molto più di ogni altra cosa ... Ma alcuni dei tuoi punti mostrano che non rispetti ciò che accade quando viene costruito e utilizzato.

  • Non tutto è compilato. Il sistema di compilazione del kernel consente di definire rapidamente configurazioni che selezionano gruppi di codice sorgente. Alcuni sono sperimentali, altri sono vecchi, altri non sono necessari per tutti i sistemi. Guarda /boot/config-$(uname -r)(su Ubuntu) in make menuconfige vedrai quanto è escluso.

    E questa è una distribuzione desktop a destinazione variabile. La configurazione di un sistema incorporato attirerebbe solo le cose di cui ha bisogno.

  • Non tutto è integrato. Nella mia configurazione, la maggior parte delle funzionalità del kernel sono costruite come moduli:

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

    Per essere chiari, questi potrebbero essere tutti integrati ... Proprio come potrebbero essere stampati e trasformati in un gigantesco sandwich di carta. Non avrebbe senso a meno che tu non stia facendo una build personalizzata per un lavoro hardware discreto (nel qual caso, avresti già limitato il numero di questi elementi).

  • I moduli vengono caricati dinamicamente. Anche quando un sistema ha migliaia di moduli disponibili, il sistema ti permetterà di caricare solo le cose di cui hai bisogno. Confronta le uscite di:

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

    Non viene caricato quasi nulla.

  • I micro kernel non sono la stessa cosa. Solo 10 secondi guardando l'immagine principale sulla pagina Wikipedia che hai collegato evidenzierebbe che sono progettati in un modo completamente diverso.

    I driver di Linux sono internalizzati (principalmente come moduli caricati dinamicamente), non spazio utente, e i filesystem sono similmente interni. Perché è peggio che usare driver esterni? Perché il micro è meglio per il calcolo per scopi generici?


I commenti evidenziano di nuovo che non lo stai ricevendo. Se si desidera distribuire Linux su hardware discreto (ad es. Aerospace, TiVo, tablet, ecc.) , Configurarlo per creare solo i driver necessari . Puoi fare lo stesso sul tuo desktop con make localmodconfig. Si finisce con un piccolo kernel Kernel per scopi specifici con flessibilità zero.

Per distribuzioni come Ubuntu, è accettabile un singolo pacchetto del kernel da 40 MB. No, scrub che, in realtà è preferibile all'enorme scenario di archiviazione e download che mantenere 4000+ moduli mobili come sarebbero i pacchetti. Utilizza meno spazio su disco per loro, più facile da impacchettare in fase di compilazione, più facile da memorizzare ed è migliore per i loro utenti (che hanno un sistema che funziona).

Nemmeno il futuro sembra essere un problema. Il tasso di miglioramenti della velocità della CPU, della densità del disco / prezzo e della larghezza di banda sembra molto più rapido della crescita del kernel. Un pacchetto del kernel da 200 MB in 10 anni non sarebbe la fine se il mondo.

Inoltre non è una strada a senso unico. Il codice viene espulso se non viene mantenuto.


2
La preoccupazione riguarda principalmente i sistemi embedded. Come mostrato, hai 4.000 moduli non in uso sul tuo sistema. In alcune piccole applicazioni di robotica o aerospaziale (LEGGI: ​​informatica non generale) questo sarebbe spreco inaccettabile.
Jonathan,

2
@JonathanLeaders Penso che tu possa eliminarli in sicurezza. Su un'installazione desktop, sono lì nel caso in cui improvvisamente colleghi qualcosa in una porta USB, o cambi un po 'di configurazione hardware, ecc.
Didier A.

1
Si, esattamente. Rimango ancora sorpreso da ipotesi come "potresti collegare un dispositivo USB in qualsiasi momento, quindi abbiamo bisogno di 15m righe di codice" sono scritte a livello di kernel , e non a livello di distro, visto che Linux è usato nel telefono e vari dispositivi integrati. Beh, credo che la distro fa abbattere la lista su di essa la propria. Penserei solo che il supporto per la connettività dovrebbe essere additivo e non sottrattivo, ovvero una distro potrebbe in qualche modo 'opt-in' aggiungendo i sorgenti del pacchetto, al contrario delle configurazioni ARM incorporate che dicono al kernel di essere l'uno percento della sua dimensione attuale
Jonathan,

5
@JonathanLeaders non avresti mai eseguito un kernel configurato per un desktop su un sistema incorporato. Il nostro sistema integrato ha 13 moduli e ha rimosso tutto il supporto hardware di cui non abbiamo bisogno (insieme a molte altre personalizzazioni). Interrompere il confronto tra desktop e sistemi integrati. Linux funziona bene perché supporta tutto e può essere personalizzato per includere solo ciò che ti interessa. E quei moduli 4K sono davvero fantastici sui sistemi desktop: quando il mio ultimo laptop è morto, ho appena messo il disco rigido in un laptop molto più recente e tutto ha funzionato .
Drewbenn,

3
Questa risposta altrimenti buona / preziosa soffre di un tono decisamente arrabbiato e combattivo. -1.
TypeIA,

19

Conteggio delle righe delle fonti compilate tinyconfig di Linux grafico a bolle tinyconfig svg (violino)

shell script per creare il json dalla build del kernel, usare con http://bl.ocks.org/mbostock/4063269


Modifica : si è scoperto che unifdefhanno alcune limitazioni ( -Iviene ignorato e -includenon supportato, quest'ultimo viene utilizzato per includere l'intestazione di configurazione generata) a questo punto l'utilizzo catnon cambia molto:

274692 total # (was 274686)

script e procedura aggiornati.


Accanto a driver, arch ecc. C'è un sacco di codice condizionale compilato o meno a seconda della configurazione scelta, codice non necessariamente nei moduli dinamici caricati ma incorporato nel core.

Quindi, scaricato linux-4.1.6 fonti , scelto tinyconfig , non abilita i moduli e sinceramente non so cosa abiliti o cosa un utente possa farne durante l'esecuzione, comunque configuro il kernel:

# tinyconfig      - Configure the tiniest possible kernel
make tinyconfig

costruito il kernel

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

il processo di compilazione del kernel lascia i file nascosti chiamati *.cmdcon la riga di comando utilizzata anche per compilare i .ofile, elaborare quei file ed estrarre la destinazione e la copia delle dipendenze di script.shseguito e usarli con find :

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

questo crea una copia per ogni dipendenza della destinazione .oindicata.o.c

codice .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 headers (sanitized)

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

@JonathanLeaders si è divertito a lavorarci, felice che a qualcuno piaccia
Alex

9

I compromessi dei chicchi monolitici sono stati discussi tra Tananbaum e Torvalds in pubblico fin dall'inizio. Se non hai bisogno di attraversare nello spazio utenti per tutto, allora l'interfaccia al kernel può essere più semplice. Se il kernel è monolitico, allora può essere più ottimizzato (e più disordinato!) Internamente.

Abbiamo avuto moduli come un compromesso per un bel po '. E continua con cose come DPDK (spostando più funzionalità di rete dal kernel). Più core vengono aggiunti, più è importante evitare il blocco; così più cose si sposteranno nello spazio utente e il kernel si ridurrà.

Nota che i kernel monolitici non sono l'unica soluzione. Su alcune architetture, il limite del kernel / spazio utente non è più costoso di qualsiasi altra chiamata di funzione, il che rende i microkernels attraenti.


1
"Su alcune architetture, il limite kernel / userspace non è più costoso di qualsiasi altra chiamata di funzione" - interessante! Quale architettura sarebbe? Sembra incredibilmente difficile da realizzare se almeno non si rinuncia a qualsiasi tipo di protezione della memoria.
Voo,

1
Ho esaminato tutti i video di millcomputing.com di Ivan Goddard (cpu mulino / cinghia, molto simile a VLIW). Questa affermazione particolare è un tema centrale e le sue implicazioni non sono evidenti fino a quando non si arriva al video sulla sicurezza. È un'architettura POC in simulazione, ma probabilmente non è l'unica architettura con questa proprietà.
Rob,

1
Ah questo lo spiega. Nella mia esperienza (e sarò il primo ad ammettere che non seguo il settore così da vicino) ci sono molte architetture simulate e poche sono all'altezza delle loro affermazioni non appena la gomma colpisce la strada, cioè vengono messe su hardware reale. Anche se l'idea alla base potrebbe essere interessante in ogni caso - non la prima volta che viene menzionata una determinata CPU. Se mai trovassi un'architettura esistente con questa proprietà, sarei davvero interessato.
Voo,

1
A proposito ecco altre risorse sul dibattito che hai citato: en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Jonathan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.