¿Por qué el kernel de Linux tiene más de 15 millones de líneas de código? [cerrado]

109

¿Cuáles son los contenidos de esta base de código monolítico?

Entiendo el soporte de la arquitectura del procesador, la seguridad y la virtualización, pero no puedo imaginar que sean más de 600,000 líneas más o menos.

¿Cuáles son los motivos históricos y actuales por los que se incluyen los controladores en la base del código del núcleo?

¿Esos más de 15 millones de líneas incluyen cada controlador para cada pieza de hardware? Si es así, entonces surge la pregunta, ¿por qué los controladores están integrados en el kernel y no paquetes separados que se detectan automáticamente e instalan desde las ID de hardware?

¿Es el tamaño de la base del código un problema para dispositivos con almacenamiento limitado o con memoria?

Parece que aumentaría el tamaño del kernel para dispositivos ARM con espacio limitado si todo eso estuviera incrustado. ¿Hay muchas líneas seleccionadas por el preprocesador? Llámame loco, pero no puedo imaginar una máquina que necesite tanta lógica para ejecutar lo que entiendo son los roles de un núcleo.

¿Hay evidencia de que el tamaño será un problema en más de 50 años debido a su naturaleza aparentemente cada vez mayor?

La inclusión de controladores significa que crecerá a medida que se haga el hardware.

EDITAR : Para aquellos que piensan que esta es la naturaleza de los núcleos, después de algunas investigaciones me di cuenta de que no siempre es así. No se requiere que un núcleo sea tan grande, ya que el microkernel Mach de Carnegie Mellon se enumeró como un ejemplo 'generalmente bajo 10,000 líneas de código'

Jonathan
fuente
99
En 2012 tenía más de 5 millones de líneas solo para conductores. 1.9 millones de líneas para soportar diferentes arquitecturas de procesador. Más información h-online.com/open/features/…
steve
11
Sí, he codificado un compilador, un analizador léxico y un generador de código de bytes para un idioma, y ​​estaba completando más recursividad y no tomó 10,000 líneas.
Jonathan
55
(lo miró ahora, eran aproximadamente 2,700 líneas)
Jonathan
44
Debe descargar y configurar make menuconfigpara ver cuánto del código se puede habilitar / deshabilitar antes de la compilación.
casey
66
@ JonathanLeaders: He terminado compiladores completos para lenguajes similares a LISP en menos de 100 líneas, con programas de prueba que representan Mandelbrots. Siempre depende.
phresnel

Respuestas:

43

Los controladores se mantienen en el núcleo, por lo que cuando un cambio en el núcleo requiere una búsqueda y reemplazo global (o modificación de búsqueda y mano) para todos los usuarios de una función, la persona que realiza el cambio lo hace. Hacer que su controlador sea actualizado por personas que realizan cambios en la API es una ventaja muy buena, en lugar de tener que hacerlo usted mismo cuando no se compila en un kernel más reciente.

La alternativa (que es lo que sucede para los controladores mantenidos fuera del árbol), es que el parche debe ser sincronizado nuevamente por sus mantenedores para mantenerse al día con cualquier cambio.

Una búsqueda rápida generó un debate sobre el desarrollo de controladores dentro del árbol o fuera del árbol .

La forma en que se mantiene Linux es principalmente manteniendo todo en el repositorio principal. La construcción de pequeños núcleos despojados es compatible con las opciones de configuración para controlar #ifdefs. Por lo tanto, puede construir absolutamente pequeños núcleos despojados que compilan solo una pequeña parte del código en todo el repositorio.

El uso extensivo de Linux en sistemas embebidos ha llevado a un mejor soporte para dejar de lado las cosas que Linux tenía años antes cuando el árbol de fuentes del núcleo era más pequeño. Un núcleo súper mínimo 4.0 es probablemente más pequeño que un núcleo súper mínimo 2.4.0.

Peter Cordes
fuente
44
Ahora, ESTO tiene sentido para mí por qué es lógico tener todo el código junto, ahorra horas hombre a costa de los recursos informáticos y las dependencias excesivas.
Jonathan
8
@ JonathanLeaders: sí, evita la descomposición de bits para los controladores con un mantenimiento no muy activo. También es probable que sea útil tener todo el código del controlador al considerar los cambios principales. La búsqueda en todas las personas que llaman de alguna API interna puede activar un controlador que lo utiliza de una manera que no pensó, lo que podría influir en un cambio en el que estaba pensando.
Peter Cordes
1
@JonathanLeaders vienen en xd, como si esas líneas adicionales ocuparan mucho espacio adicional, en las medidas modernas de instalación en una PC.
Junaga
3
@Junaga: te das cuenta de que Linux es muy portátil y escalable, ¿verdad? El desperdicio de 1 MB de memoria de kernel usada permanentemente en un sistema embebido de 32 MB es un gran problema. El tamaño del código fuente no es importante, pero el tamaño binario compilado sigue siendo importante. La memoria del kernel no está paginada, por lo que incluso con el espacio de intercambio no puede recuperarla.
Peter Cordes
1
@Rolf: Es grande, pero es no espaguetis. Actualmente está bastante bien diseñado sin dependencias bidireccionales entre el código central y los controladores. Los controladores pueden omitirse sin romper el núcleo del núcleo. Cuando se refactoriza una función interna o API, por lo que los controladores deben usarla de manera diferente, los controladores pueden necesitar cambiar, pero eso es normal para la refactorización.
Peter Cordes
79

De acuerdo con cloc ejecutado contra 3.13, Linux tiene aproximadamente 12 millones de líneas de código.

  • 7 millones de LOC en conductores /
  • 2 millones de LOC en arco /
  • solo 139 mil LOC en kernel /

lsmod | wc en mi computadora portátil Debian se muestran 158 módulos cargados en tiempo de ejecución, por lo que cargar módulos dinámicamente es una forma muy utilizada de soportar hardware.

El sistema de configuración robusto (p make menuconfig. Ej. ) Se utiliza para seleccionar qué código compilar (y más a su punto, qué código no compilar). Los sistemas integrados definen su propio .configarchivo con el soporte de hardware que les interesa (incluido el soporte de hardware integrado en el núcleo o como módulos cargables).

drewbenn
fuente
3
el conteo de módulos no es suficiente, muchos pueden estar construidos por configuración
Alex
55
Creo que de esto podemos concluir que el kernel de Linux es masivo porque admite todo tipo de configuraciones de dispositivos, no porque sea escandalosamente complejo. Vemos aquí que muy pocas de las líneas de 15m están realmente en uso. Aunque, como casi todas las cosas son, puede ser demasiado complejo, al menos podemos dormir por la noche sabiendo que está dentro de lo razonable
Jonathan
2
@JonathanLeaders: Sí, y además de módulos para dispositivos extraños, hay módulos para sistemas de archivos oscuros, protocolos de red, etc ...
psmears
66
@JonathanLeader Recuerdo cuando Linux se estaba iniciando, incluso hacer que el instalador funcionara (¡si es que tenía un instalador!) Fue un gran problema, todavía hay algunas distribuciones en las que debes elegir el controlador de tu mouse manualmente. Hacer cosas como la creación de redes o, Dios no lo quiera, X-window, trabajar, era un rito de iniciación. En mi primera instalación de Red Hat, tuve que escribir mi propio controlador de gráficos, porque solo había tres (!) Controladores disponibles. Tener un funcionamiento básico por defecto es un signo de madurez, y obviamente, puede permitirse muchos más ajustes en un sistema integrado, donde solo hay unas pocas combinaciones de HW.
Luaan
2
@JonathanLeaders Como creo que te has dado cuenta, el LOC en la fuente es más o menos irrelevante. Si desea saber cuánta memoria usa el núcleo, hay formas mucho más directas .
Ricitos
67

Para cualquier persona curiosa, aquí está el desglose del recuento de líneas para el espejo 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
=============================================

driverscontribuye a gran parte del recuento de líneas.

usuario3276552
fuente
19
Eso es interesante. Aún más interesantes son los puntos potencialmente débiles en el código, donde los programadores estaban molestos:grep -Pir "\x66\x75\x63\x6b" /usr/src/linux/ | wc -l
jimmij
44
@jimmij '\ x73 \ x68 \ x69 \ x74' podría ser más común según esta investigación innovadora (aunque ligeramente anticuada) .
Nick T
3
Hecho aleatorio: la carpeta que está más cerca del 600 000 LOC estimado por el OP es la documentación.
Davidmh
1
./documentationtiene más de 500,000 líneas de código? ....¿qué?
C_B
1
@drewbenn Lo entendí más como "la documentación no está vacía?"
Izkata
43

Las respuestas hasta ahora parecen ser "sí, hay mucho código" y nadie está abordando la pregunta con la respuesta más lógica: ¿ 15M +? ¿Y QUÉ? ¿Qué tienen que ver las 15 millones de líneas de código fuente con el precio del pescado? ¿Qué hace que esto sea tan inimaginable?

Linux claramente hace mucho. Mucho más que cualquier otra cosa ... Pero algunos de sus puntos muestran que no respeta lo que sucede cuando se construye y usa.

  • No todo está compilado. El sistema de compilación Kernel le permite definir rápidamente configuraciones que seleccionan conjuntos de código fuente. Algunos son experimentales, algunos son viejos, algunos simplemente no son necesarios para todos los sistemas. Mire /boot/config-$(uname -r)(en Ubuntu) make menuconfigy verá cuánto está excluido.

    Y esa es una distribución de escritorio de destino variable. La configuración para un sistema incrustado solo atraerá las cosas que necesita.

  • No todo está incorporado. En mi configuración, la mayoría de las características del Kernel se crean como módulos:

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

    Para ser claros, todos estos podrían incorporarse ... Así como podrían imprimirse y convertirse en un sándwich de papel gigante. Simplemente no tendría sentido a menos que estuviera haciendo una compilación personalizada para un trabajo de hardware discreto (en cuyo caso, ya habría limitado el número de estos elementos).

  • Los módulos se cargan dinámicamente. Incluso cuando un sistema tiene miles de módulos disponibles, el sistema le permitirá cargar solo lo que necesita. Compare las salidas de:

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

    Casi nada está cargado.

  • Los microkernels no son lo mismo. Solo 10 segundos mirando la imagen principal de la página de Wikipedia que vinculaste destacaría que están diseñados de una manera completamente diferente.

    Los controladores de Linux están internalizados (principalmente como módulos cargados dinámicamente), no en el espacio de usuario, y los sistemas de archivos son igualmente internos. ¿Por qué es peor que usar controladores externos? ¿Por qué es micro mejor para la informática de propósito general?


Los comentarios nuevamente resaltan que no lo estás entendiendo. Si desea implementar Linux en hardware discreto (por ejemplo, aeroespacial, un TiVo, tableta, etc.) , configúrelo para construir solo los controladores que necesita . Puede hacer lo mismo en su escritorio con make localmodconfig. Terminas con una pequeña construcción de Kernel con cero flexibilidad.

Para distribuciones como Ubuntu, se acepta un solo paquete Kernel de 40 MB. No, elimine eso, en realidad es preferible al archivado masivo y al escenario de descarga que mantendría más de 4000 módulos flotantes como paquetes. Utiliza menos espacio en disco para ellos, es más fácil de empaquetar en tiempo de compilación, es más fácil de almacenar y es mejor para sus usuarios (que tienen un sistema que simplemente funciona).

El futuro tampoco parece ser un problema. La velocidad de la CPU, la densidad / fijación de precios del disco y las mejoras en el ancho de banda parecen mucho más rápidas que el crecimiento del Kernel. Un paquete de Kernel de 200 MB en 10 años no sería el final si el mundo fuera.

Tampoco es una calle de sentido único. El código se expulsa si no se mantiene.

Oli
fuente
2
La preocupación es principalmente para los sistemas integrados. Como muestra, tiene 4.000 módulos que no están en uso en su propio sistema. En algunas aplicaciones pequeñas de robótica o aeroespacial, (LEER: no computación de propósito general) esto sería un desperdicio inaceptable.
Jonathan
2
@ JonathanLeaders Creo que puedes eliminarlos de forma segura. En una instalación de escritorio, están allí en caso de que de repente conecte algo en un puerto usb, o cambie alguna configuración de hardware, etc.
Didier A.
1
Sí exactamente. Todavía me sorprenden las suposiciones como "se puede conectar un dispositivo USB en cualquier momento, por lo tanto, necesitamos 15 millones de líneas de código" están escritas en el nivel del núcleo , y no en el nivel de distribución, ya que Linux se usa en el teléfono y otros dispositivos integrados. Bueno, supongo que la distribución elimina la lista por sí misma. Solo pensaría que el soporte para la capacidad de conexión debería ser aditivo y no sustractivo, es decir, una distribución podría 'optar por' agregar fuentes de paquetes, en lugar de configuraciones ARM incrustadas que le dicen al núcleo que sea el uno por ciento de su tamaño actual
Jonathan
55
@JonathanLeaders, nunca ejecutarías un kernel configurado para un escritorio en un sistema integrado. Nuestro sistema integrado tiene 13 módulos y ha eliminado todo el soporte de hardware que no necesitamos (junto con muchas otras personalizaciones). Deje de comparar escritorios con sistemas integrados. Linux funciona bien porque admite todo y se puede personalizar para incluir solo lo que le interesa. Y esos módulos 4k son realmente geniales en los sistemas de escritorio: cuando murió mi última computadora portátil, simplemente puse el disco duro en una computadora portátil mucho más nueva y todo funcionó .
drewbenn
3
Esta respuesta buena / valiosa sufre de un tono claramente enojado y combativo. -1.
TypeIA
19

Recuento de líneas de fuentes compiladas de Linuxconconfig svg de gráfico de burbuja tinyconfig (violín)

script de shell para crear el json desde la compilación del núcleo, úselo con http://bl.ocks.org/mbostock/4063269


Editar : resultó unifdeftener alguna limitación ( -Ise ignora y -includeno es compatible, este último se usa para incluir el encabezado de configuración generado) en este punto, el uso catno cambia mucho:

274692 total # (was 274686)

guión y procedimiento actualizado.


Además de los controladores, el arco, etc., hay una gran cantidad de código condicional compilado o no, dependiendo de la configuración elegida, código no necesariamente en módulos dinámicos cargados sino integrados en el núcleo.

Entonces, descargué las fuentes de linux-4.1.6 , elegí el tinyconfig , no habilita los módulos y honestamente no sé qué habilita o qué puede hacer un usuario con él en tiempo de ejecución, de todos modos, configure el kernel:

# tinyconfig      - Configure the tiniest possible kernel
make tinyconfig

construido el núcleo

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

el proceso de compilación del kernel deja los archivos ocultos llamados *.cmdcon la línea de comando utilizada también para compilar .oarchivos, procesar esos archivos y extraer el objetivo y las dependencias que se copian a script.shcontinuación y usarlo con find :

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

Esto crea una copia para cada dependencia del objetivo .ollamado.o.c

código .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 encabezados (desinfectados)

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
fuente
@JonathanLeaders ha sido divertido trabajar en ello, me alegra que a alguien le guste
Alex
9

Las compensaciones de los granos monolíticos se debatieron entre Tananbaum y Torvalds en público desde el principio. Si no necesita cruzar al espacio de usuario para todo, entonces la interfaz al núcleo puede ser más simple. Si el núcleo es monolítico, entonces puede ser más optimizado (¡y más desordenado!) Internamente.

Hemos tenido módulos como compromiso durante bastante tiempo. Y continúa con cosas como DPDK (mover más funciones de red fuera del núcleo). Cuantos más núcleos se agregan, más importante es evitar el bloqueo; así que más cosas se moverán al espacio de usuario y el núcleo se reducirá.

Tenga en cuenta que los núcleos monolíticos no son la única solución. En algunas arquitecturas, el límite del núcleo / espacio de usuario no es más costoso que cualquier otra llamada de función, lo que hace que los microkernels sean atractivos.

Robar
fuente
1
"En algunas arquitecturas, el límite del núcleo / espacio de usuario no es más costoso que cualquier otra llamada de función" - ¡interesante! ¿Qué arquitectura sería esa? Parece increíblemente difícil de lograr si no abandonas al menos cualquier tipo de protección de memoria.
Voo
1
Revisé todos los videos de millcomputing.com de Ivan Goddard (cpu de mill / belt, muy similar a VLIW). Este reclamo en particular es un tema central, y sus implicaciones no son obvias hasta que llegue al video de seguridad. Es una arquitectura POC en simulación, pero probablemente no sea la única arquitectura con esta propiedad.
Rob
1
Ah eso lo explica. En mi experiencia (y seré el primero en admitir que no sigo a la industria tan de cerca) hay muchas arquitecturas simuladas y pocas están a la altura de sus afirmaciones tan pronto como el caucho llega a la carretera, es decir, se ponen en hardware real. Aunque la idea detrás de esto puede ser interesante en cualquier caso, no es la primera vez que se menciona esa CPU en particular. Si alguna vez encuentra una arquitectura existente que tenga esta propiedad, estaría realmente interesado.
Voo
1
Por cierto, aquí hay más recursos sobre el debate que mencionó: en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Jonathan