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

102

Qual é o conteúdo desta base de código monolítico?

Eu entendo o suporte, a segurança e a virtualização da arquitetura do processador, mas não consigo imaginar que sejam mais de 600.000 linhas ou mais.

Quais são os históricos & motivo atual drivers estão incluídos na base de código do kernel?

Esses mais de 15 milhões de linhas incluem todos os drivers para cada peça de hardware? Se assim for, então, pergunta: por que os drivers estão embutidos no kernel e não separam pacotes que são detectados automaticamente e instalados a partir de IDs de hardware?

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

Parece que iria aumentar o tamanho do kernel para dispositivos ARM com restrição de espaço se tudo isso fosse incorporado. Muitas linhas são selecionadas pelo pré-processador? Me chame de louco, mas não consigo imaginar uma máquina que precise de muita lógica para executar o que eu entendo é o papel de um kernel.

Existe evidência de que o tamanho será um problema em mais de 50 anos devido a sua natureza aparentemente crescente?

A inclusão de drivers significa que ele crescerá conforme o hardware for feito.

EDITAR : Para aqueles que pensam que esta é a natureza dos kernels, depois de algumas pesquisas, percebi que nem sempre é assim. Não é necessário que um kernel seja tão grande, já que o microkernel do Carnegie Mellon foi listado como um exemplo 'geralmente abaixo de 10.000 linhas de código '

    
por Jonathan 17.08.2015 / 19:04

6 respostas

40

Os drivers são mantidos no kernel, portanto, quando uma alteração no kernel exige uma pesquisa e substituição global (ou pesquisa e modificação manual) para todos os usuários de uma função, ela é feita pela pessoa que faz a alteração. Ter seu driver atualizado por pessoas fazendo alterações na API é uma vantagem muito boa, em vez de ter que fazer isso sozinho quando ele não é compilado em um kernel mais recente.

A alternativa (que é o que acontece para os drivers mantidos fora da árvore), é que o patch tem que ser re-sincronizado pelos seus mantenedores para acompanhar quaisquer alterações.

Uma pesquisa rápida revelou um debate sobre desenvolvimento de drivers na árvore vs. fora da árvore .

A maneira como o Linux é mantido é principalmente mantendo tudo no repositório mainline. O desenvolvimento de pequenos kernels despojados é suportado pelas opções de configuração para controlar #ifdef s. Então 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 o material fora do Linux anos antes, quando a árvore de código-fonte do kernel era menor. Um kernel 4.0 super-minimal é provavelmente menor que um kernel 2.4.0 super-minimal.

    
por 19.08.2015 / 06:31
74

De acordo com o cloc executado em relação ao 3.13, o Linux tem cerca de 12 milhões de linhas de código.

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

lsmod | wc no meu laptop Debian mostra 158 módulos carregados em tempo de execução, então carregar dinamicamente 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 para o seu ponto, qual código para não compilar). Os sistemas embarcados definem seu próprio arquivo .config apenas com o suporte de hardware de que gostam (incluindo hardware de suporte integrado ao kernel ou como módulos carregáveis).

    
por 17.08.2015 / 19:42
61

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

drivers contribui para um lote da contagem de linhas.

    
por 17.08.2015 / 20:13
42

As respostas até agora parecem ser "sim, há muito código" e ninguém está respondendo à pergunta com a resposta mais lógica: 15M +? ASSIM O QUE? O que as linhas 15M do 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 que você defina rapidamente as configurações que selecionam conjuntos de código-fonte. Alguns são experimentais, alguns são antigos, outros não são necessários para todos os sistemas. Veja /boot/config-$(uname -r) (no Ubuntu) em make menuconfig e você verá o quanto está excluído.

    E essa é uma distribuição de desktop com segmentação variável. A configuração de um sistema embarcado só traria as coisas de que precisa.

  • Nem tudo é interno. Na minha configuração, a maioria dos recursos do Kernel é construída como módulos:

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

    Para ser claro, estes poderiam todos ser incorporados ... Assim como eles poderiam ser impressos e transformados em um sanduíche de papel gigante. Isso não faria sentido a menos que você estivesse fazendo uma compilação personalizada para um trabalho de hardware separado (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 permite carregar apenas as coisas que você precisa. Compare as saídas de:

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

    Quase nada é carregado.

  • Microkernels não são a mesma coisa. Apenas 10 segundos olhando a imagem principal para a página da Wikipedia você vinculado destacaria que eles são 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 similarmente internos. Por que isso é pior do que usar drivers externos? Por que o micro é melhor para computação de propósito geral?

Os comentários novamente destacam que você não está entendendo. Se você quiser implantar o Linux em hardware separado (por exemplo, aeroespacial, um TiVo, tablet, etc), você o configura para criar apenas os drivers necessários . Você pode fazer o mesmo em sua área de trabalho com make localmodconfig . Você acaba com uma pequena construção Kernel para fins específicos com flexibilidade zero.

Para distribuições como o Ubuntu, um pacote único de 40MB é aceitável. Não, esfregue isso, na verdade é preferível ao cenário massivo de arquivamento e download que mantém 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 do disco / preço e melhorias na largura de banda parece muito mais rápida do que o crescimento do Kernel. Um pacote de 200MB Kernel em 10 anos não seria o fim se o mundo.

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

    
por 18.08.2015 / 11:55
17

tinyconfig bubble graph svg (violino)

script de shell para criar o json a partir da compilação do kernel, use com link

Editar : resultado unifdef tem alguma limitação ( -I é ignorado e -include não suportado, o último é usado para incluir o cabeçalho de configuração gerado) usando cat não muda muito:

274692 total # (was 274686)

script e procedimento atualizados.

Além de drivers, arch, etc., há um monte de código condicional compilado ou não, dependendo da configuração escolhida, código não necessariamente em módulos carregados dinamicamente, mas embutido no núcleo.

Então, baixado linux-4.1.6 sources , peguei o tinyconfig , ele não habilita módulos e eu sinceramente não sei o que habilita ou o que um usuário pode fazer com ele em tempo de execução, enfim, config 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 criação do kernel deixa arquivos ocultos chamados *.cmd com a linha de comando usada também para construir .o arquivos, para processar esses arquivos e extrair destino e dependências copie script.sh abaixo e use-o com find :

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

isso cria uma cópia para cada dependência do destino .o named .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
    
por 17.08.2015 / 20:39
8

As compensações de grãos monolíticos foram debatidas entre Tananbaum e Torvalds em público desde o início. Se você não precisa entrar no userspace para tudo, então a interface para o kernel pode ser mais simples. Se o kernel é monolítico, então ele pode ser mais otimizado (e mais bagunçado!) Internamente.

Nós tivemos módulos como um compromisso por 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; então mais coisas irão para o espaço do usuário e o kernel irá encolher.

Note que os kernels monolíticos não são a única solução. Em algumas arquiteturas, o limite do kernel / userspace não é mais caro do que qualquer outra chamada de função, tornando os microkernels atraentes.

    
por 18.08.2015 / 19:28