Por que o kernel Linux tem mais de 15 milhões de linhas de código? [fechadas]

109

Qual é o conteúdo dessa base de código monolítica?

Entendo o suporte à arquitetura do processador, a segurança e a virtualização, mas não consigo imaginar que sejam mais de 600.000 linhas.

Quais são os motivos históricos e atuais dos drivers incluídos na base de código do kernel?

Essas mais de 15 milhões de linhas incluem todos os drivers para cada peça de hardware de todos os tempos? Em caso afirmativo, isso levanta a questão: por que os drivers são incorporados ao kernel e não separam pacotes detectados e instalados automaticamente a partir de IDs de hardware?

O tamanho da base de código é um problema para dispositivos com restrição de armazenamento ou memória?

Parece que aumentaria o tamanho do kernel para dispositivos ARM com espaço limitado, se tudo isso fosse incorporado. Muitas linhas são selecionadas pelo pré-processador? Me chame de louca, mas não consigo imaginar uma máquina que precise de tanta lógica para executar o que entendo são os papéis de um kernel.

Há evidências de que o tamanho será um problema em mais de 50 anos devido à sua natureza aparentemente crescente?

Incluir drivers significa que ele crescerá à medida que o hardware for fabricado.

EDIT : Para aqueles que pensam que essa é a natureza dos kernels, depois de algumas pesquisas, percebi que nem sempre é. Não é necessário que um kernel seja tão grande, pois o microkernel Mach de Carnegie Mellon foi listado como um exemplo 'geralmente com menos de 10.000 linhas de código'

Jonathan
fonte
9
Em 2012, tinha mais de 5 milhões de linhas apenas para motoristas. 1,9 milhão de linhas para suportar diferentes arquiteturas de processador. Mais informações h-online.com/open/features/…
steve
11
Sim, eu codifiquei um compilador, analisador lexical e gerador de código de bytes para um idioma, e estava completo mais a recursão e não levou 10.000 linhas.
Jonathan
5
(olhou para ele agora, era cerca de 2.700 linhas)
Jonathan
4
Você deve fazer o download e configurar make menuconfigpara ver quanto do código pode ser ativado / desativado antes da criação.
Casey
6
@ JonathanLeaders: Eu fiz turing compiladores completos para linguagens como LISP em menos de 100 linhas, com programas de teste renderizando Mandelbrots. Sempre depende.
Phd

Respostas:

43

Os drivers são mantidos no kernel; portanto, quando uma alteração no kernel requer uma pesquisa e substituição global (ou pesquisa e modificação manual) para todos os usuários de uma função, isso é feito pela pessoa que faz a alteração. Atualizar o driver por pessoas que fazem alterações na API é uma vantagem muito boa, em vez de precisar fazer isso sozinho, quando não compila em um kernel mais recente.

A alternativa (o que acontece com os drivers mantidos fora da árvore) é que o patch precisa ser sincronizado novamente por seus mantenedores para acompanhar as alterações.

Uma pesquisa rápida gerou um debate sobre o desenvolvimento de drivers in-tree vs. out-of-tree .

A maneira como o Linux é mantido é principalmente mantendo tudo no repositório principal. A construção de pequenos kernels despojados é suportada por opções de configuração para controlar #ifdefs. Portanto, você pode absolutamente construir minúsculos kernels despojados que compilam apenas uma pequena parte do código em todo o repositório.

O uso extensivo do Linux em sistemas embarcados levou a um melhor suporte para deixar de fora as coisas do que o Linux tinha anos antes, quando a árvore de fontes do kernel era menor. Um kernel super-mínimo 4.0 é provavelmente menor que um kernel 2.4.0 super-mínimo.

Peter Cordes
fonte
4
Agora, isso faz sentido para mim, por que é lógico ter todo o código juntos, economiza horas de trabalho com o custo de recursos do computador e dependências excessivas.
Jonathan
8
@ JonathanLeaders: sim, evita a podridão dos bits para motoristas com manutenção não muito ativa. Provavelmente também é útil ter todo o código do driver ao considerar as alterações principais. A pesquisa em todos os chamadores de alguma API interna pode ativar um driver usando-o de uma maneira que você não pensou, potencialmente influenciando uma alteração em que estava pensando.
22815 Peter Cordes
1
@ JonathanLeaders vem no xd, como se essas linhas extras ocupassem muito espaço extra, nas medidas modernas de instalação em um PC.
Junaga
3
@Junaga: você percebe que o linux é muito portátil e escalável, certo? A perda de 1 MB de memória de kernel usada permanentemente em um sistema incorporado de 32 MB é um grande problema. O tamanho do código-fonte não é importante, mas o tamanho binário compilado ainda é importante. A memória do kernel não é paginada, portanto, mesmo com espaço de troca, você não pode recuperá-la.
26616 Peter Cordes
1
@Rolf: É grande, mas é não spaghetti. Atualmente, está bem arquitetado, sem dependências bidirecionais entre o código principal e os drivers. Os drivers podem ser deixados de fora sem quebrar o núcleo do kernel. Quando uma função interna ou API é refatorada, para que os drivers precisem usá-la de maneira diferente, os drivers podem precisar mudar, mas isso é normal para refatoração.
Peter Cordes
79

De acordo com o cloc executado na versão 3.13, o Linux possui cerca de 12 milhões de linhas de código.

  • 7 milhões de LOC em motoristas /
  • 2 milhões de LOC em arco /
  • apenas 139 mil LOC no kernel /

lsmod | wc no meu laptop Debian mostra 158 módulos carregados em tempo de execução; portanto, carregar dinamicamente os módulos é uma maneira bem usada de suportar hardware.

O sistema de configuração robusto (por exemplo make menuconfig) é usado para selecionar qual código compilar (e mais ao seu ponto, qual código não compilar). Os sistemas incorporados definem seu próprio .configarquivo apenas com o suporte de hardware de que se preocupam (incluindo o suporte ao hardware incorporado ao kernel ou como módulos carregáveis).

Drewbenn
fonte
3
contando módulos não é suficiente, muito talvez embutido pela configuração
Alex
5
Acho que podemos concluir que o kernel do Linux é massivo porque suporta todos os tipos de configurações de dispositivos, não porque é escandalosamente complexo. Vemos aqui que muito poucas linhas de 15m estão realmente em uso. Embora, como quase todas as coisas são, pode ser excessivamente complexa, pelo menos podemos dormir à noite sabendo que é dentro da razão
Jonathan
2
@JonathanLeaders: Sim - e, assim como módulos para dispositivos estranhos, existem módulos para sistemas de arquivos obscuros, protocolos de rede, etc ...
psmears
6
@ JonathanLeader Lembro-me de quando o Linux estava iniciando - até fazer o instalador funcionar (se ele tivesse um instalador!) Foi uma dor enorme - ainda há algumas distros nas quais você precisa escolher o driver do mouse manualmente. Fazer coisas como trabalhar em rede ou, se Deus permitir, janelas X, funcionar, era um rito de passagem. Na minha primeira instalação do Red Hat, tive que escrever meu próprio driver gráfico, porque havia apenas três (!) Drivers disponíveis. Ter o trabalho básico por padrão é um sinal de maturidade - e, obviamente, você pode permitir muito mais ajustes em um sistema incorporado, onde há apenas algumas combinações de HW.
Luaan
2
@ JonathanLeaders Como eu acho que você já percebeu, o LOC na fonte é mais ou menos irrelevante. Se você quiser saber quanta memória o kernel usa, existem maneiras muito mais diretas .
Goldilocks
67

Para qualquer pessoa curiosa, aqui está o detalhamento da contagem de linha para o espelho do 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
=============================================

driverscontribui para grande parte da contagem de linha.

user3276552
fonte
19
Isso é interessante. Ainda mais interessante são os pontos potencialmente fracos no código, onde os programadores estavam irritados:grep -Pir "\x66\x75\x63\x6b" /usr/src/linux/ | wc -l
jimmij
4
@jimmij '\ x73 \ x68 \ x69 \ x74' pode ser mais comum de acordo com esta pesquisa inovadora (se um pouco datada) .
Nick T
3
Fato aleatório: a pasta que está mais próxima dos 600.000 LOC estimados pelo OP é a documentação.
Davidmh
1
./documentationtem mais de 500.000 linhas de código? ....o que?
C_B
1
@drewbenn eu entendi mais como "a documentação não está vazia?"
Izkata
43

As respostas até agora parecem ser "sim, há muito código" e ninguém está abordando a questão com a resposta mais lógica: 15M +? E DAÍ? O que 15M linhas de código fonte têm a ver com o preço do peixe? O que torna isso tão inimaginável?

O Linux claramente faz muito. Muito mais do que qualquer outra coisa ... Mas alguns de seus pontos mostram que você não respeita o que está acontecendo quando é construído e usado.

  • Nem tudo é compilado. O sistema de compilação do Kernel permite definir rapidamente configurações que selecionam conjuntos de códigos-fonte. Alguns são experimentais, alguns são antigos, outros simplesmente não são necessários para todos os sistemas. Veja /boot/config-$(uname -r)(no Ubuntu) em make menuconfige você verá quanto é excluído.

    E essa é uma distribuição de desktop com destino variável. A configuração de um sistema embarcado apenas atrai as coisas necessárias.

  • Nem tudo está embutido. Na minha configuração, a maioria dos recursos do Kernel são construídos como módulos:

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

    Para ser claro, tudo isso pode ser incorporado ... Assim como eles podem ser impressos e transformados em um sanduíche de papel gigante. Isso não faria sentido, a menos que você estivesse fazendo uma construção personalizada para um trabalho de hardware discreto (nesse caso, você já teria limitado o número desses itens).

  • Os módulos são carregados dinamicamente. Mesmo quando um sistema tem milhares de módulos disponíveis, o sistema permitirá que você carregue exatamente o que precisa. Compare as saídas de:

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

    Quase nada está carregado.

  • Microkernels não são a mesma coisa. Apenas 10 segundos olhando para a imagem principal da página da Wikipedia que você vinculou destacaria que eles foram projetados de uma maneira completamente diferente.

    Os drivers do Linux são internalizados (principalmente como módulos carregados dinamicamente), não o espaço do usuário, e os sistemas de arquivos são igualmente internos. Por que isso é pior do que usar drivers externos? Por que o micro é melhor para computação de uso geral?


Os comentários novamente destacam que você não está entendendo. Se você deseja implantar o Linux em hardware discreto (por exemplo, aeroespacial, TiVo, tablet etc.), configure-o para criar apenas os drivers necessários . Você pode fazer o mesmo na sua área de trabalho com make localmodconfig. Você acaba com uma compilação minúscula e específica do Kernel com flexibilidade zero.

Para distribuições como o Ubuntu, um único pacote de 40 MB do Kernel é aceitável. Não, esfregue isso, é realmente preferível ao cenário maciço de arquivamento e download que manteria mais de 4000 módulos flutuantes como pacotes. Ele usa menos espaço em disco para eles, mais fácil de empacotar em tempo de compilação, mais fácil de armazenar e é melhor para seus usuários (que possuem um sistema que simplesmente funciona).

O futuro também não parece ser um problema. A taxa de velocidade da CPU, densidade de disco / preço e melhorias na largura de banda parecem muito mais rápidos que o crescimento do Kernel. Um pacote de 200 MB do Kernel em 10 anos não seria o fim se o mundo.

Também não é uma rua de mão única. O código é expulso se não for mantido.

Oli
fonte
2
A preocupação é principalmente com sistemas embarcados. Como você mostra, você tem 4.000 módulos que não estão em uso em seu próprio sistema. Em algumas pequenas aplicações de robótica ou aeroespacial, (LEIA: computação não de uso geral), isso seria um desperdício inaceitável.
Jonathan
2
@ JonathanLeaders Eu acho que você pode excluí-los com segurança. Em instalar um desktop, eles estão lá no caso de você de repente ligar algo em uma porta USB, ou alterar algumas configurações de hardware, etc.
Didier A.
1
Sim, exatamente. Eu ainda permaneço surpreso com suposições como "você pode conectar um dispositivo USB a qualquer momento, portanto, precisamos de 15m linhas de código" são escritas no nível do kernel , e não no nível da distribuição, visto que o Linux é usado no telefone e em vários dispositivos incorporados. Bem, eu acho que a distro faz abater a lista por si própria. Eu acho que o suporte à conectividade deve ser aditivo e não subtrativo, ou seja, uma distro seria 'opt-in' adicionando fontes de pacotes, em oposição às configurações incorporadas do ARM, informando que o kernel é um por cento do tamanho atual
Jonathan
5
@ JonathanLeaders, você nunca executaria um kernel configurado para uma área de trabalho em um sistema incorporado. Nosso sistema incorporado possui 13 módulos e removeu todo o suporte de hardware que não precisamos (junto com muitas outras personalizações). Pare de comparar desktops com sistemas embarcados. O Linux funciona bem porque suporta tudo e pode ser personalizado para incluir apenas o que você gosta. E esses módulos de 4k são realmente ótimos em sistemas de desktop: quando meu último laptop morreu, apenas coloquei o disco rígido em um laptop muito mais novo e tudo funcionou .
precisa saber é o seguinte
3
Caso contrário, essa resposta boa / valiosa sofre um tom nitidamente zangado e combativo. -1.
TypeIA
19

Contagem de linhas de fontes compiladas tinyconfig do Linux tinyconfig gráfico de bolhas svg (violino)

shell script para criar o json a partir da compilação do kernel, use com http://bl.ocks.org/mbostock/4063269


Edit : acabou unifdeftendo alguma limitação ( -Ié ignorado e -includenão é suportado; o último é usado para incluir o cabeçalho de configuração gerado) neste ponto, usando catnão muda muito:

274692 total # (was 274686)

script e procedimento atualizados.


Além de drivers, arco etc., há muito código condicional compilado ou não, dependendo da configuração escolhida, código não necessariamente em módulos carregados dinâmicos, mas construído no núcleo.

Então, baixei fontes linux-4.1.6 , peguei o tinyconfig , ele não habilita módulos e eu sinceramente não sei o que habilitar ou o que um usuário pode fazer com ele em tempo de execução, de qualquer forma, configure o kernel:

# tinyconfig      - Configure the tiniest possible kernel
make tinyconfig

construiu o kernel

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

o processo de compilação do kernel deixa arquivos ocultos chamados *.cmdcom a linha de comando usada também para compilar .oarquivos, para processar esses arquivos e extrair a cópia de destino e dependências script.shabaixo e usá-la com find :

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

isso cria uma cópia para cada dependência do destino .onomeado.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 cabeçalhos (higienizados)

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
fonte
@JonathanLeaders sido divertido trabalhar sobre ela, feliz que alguém como ele
Alex
9

As compensações dos núcleos monolíticos foram debatidas entre Tananbaum e Torvalds em público desde o início. Se você não precisa acessar o espaço do usuário para tudo, a interface para o kernel pode ser mais simples. Se o kernel for monolítico, ele poderá ser mais otimizado (e mais confuso!) Internamente.

Temos módulos como compromisso há um bom tempo. E continua com coisas como DPDK (movendo mais funcionalidades de rede do kernel). Quanto mais núcleos forem adicionados, mais importante será evitar o bloqueio; assim, mais coisas serão movidas para o espaço do usuário e o kernel diminuirá.

Observe que os núcleos monolíticos não são a única solução. Em algumas arquiteturas, o limite do kernel / espaço do usuário não é mais caro do que qualquer outra chamada de função, tornando os microkernels atraentes.

Roubar
fonte
1
"Em algumas arquiteturas, o limite do kernel / espaço do usuário não é mais caro do que qualquer outra chamada de função" - interessante! Que arquitetura seria essa? Parece incrivelmente difícil de executar se você não abandonar pelo menos qualquer tipo de proteção de memória.
Voo
1
Passei por todos os vídeos de millcomputing.com de Ivan Goddard (CPU de moinho / correia, muito parecido com VLIW). Essa afirmação em particular é um tema central e suas implicações não são óbvias até você chegar ao vídeo de segurança. É uma arquitetura POC em simulação, mas provavelmente não é a única arquitetura com essa propriedade.
Rob
1
Ah, isso explica isso. Na minha experiência (e eu serei o primeiro a admitir que não acompanho a indústria tão de perto), existem muitas arquiteturas simuladas e poucas cumprem suas reivindicações assim que a borracha entra na estrada, ou seja, são colocadas em hardware real. Embora a idéia por trás disso possa ser interessante em qualquer caso - não é a primeira vez que uma CPU específica é mencionada. Se você encontrar uma arquitetura existente que possua essa propriedade, eu estaria realmente interessado.
Voo
1
BTW aqui está mais recursos no debate que você mencionou: en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Jonathan