Linux: Entendendo o Kernel
Publicado em 14/10/2008 – 19:33por Carlos Morimoto
Hoje em dia, quando falamos em "Linux" estamos normalmente nos referindo à plataforma como um todo, incluindo as diferentes distribuições e softwares. Mas, no início, o Linux era apenas o kernel desenvolvido pelo Linus Torvalds. Mesmo hoje em dia, alguns puristas ainda insistem na idéia de que o "Linux" é apenas o kernel e todos os outros componentes são softwares que rodam sobre ele. O principal argumento a favor dessa idéia é que outros sistemas Unix, como o FreeBSD e o Solaris são baseados em outros kernels (e são por isso considerados sistemas diferentes) mas, apesar disso, rodam o X, KDE, Firefox e outros softwares, assim como no caso das distribuições Linux. De qualquer forma, a idéia de usar o termo Linux para a plataforma como um todo é bem mais simples e natural, por isso adoto esta terminologia no livro.
O Kernel é a peça fundamental do sistema, responsável por prover a infra-estrutura básica necessária para que os programas funcionem, além de ser o responsável por dar suporte aos mais diferentes periféricos: placas de rede, som e o que mais você tiver espetado no micro.
Esta é justamente uma das principais diferenças entre o Windows e as distribuições Linux. No Windows, o sistema inclui um conjunto relativamente pequeno de drivers e você depende dos CDs de instalação e dos drivers disponibilizados pelos fabricantes. No Linux, quase todos os drivers disponíveis são incorporados diretamente no Kernel e já vêm pré-instalados nas distribuições. Isso faz com que os periféricos suportados sejam detectados automaticamente.
Isso faz com que a importância de usar uma distribuição atual seja muito maior, já que uma distribuição antiga ou desatualizada incluirá não apenas softwares antigos, mas também um conjunto desatualizado de drivers, que farão com que muitos comentes do PC não sejam reconhecidos.
Começando do início, se você der uma olhada dentro da pasta "/boot" de qualquer distribuição Linux, vai encontrar o executável do Kernel, no meio de um pequeno conjunto de arquivos. Ele é o primeiro componente carregado pelo gerenciador de boot durante a inicialização do sistema:

Você deve estar se perguntando por que o arquivo se chama "vmlinuz" e não "vmlinux", como seria mais lógico. Na verdade, esta é uma longa história, mas, em resumo, o "z" no nome é usado porque o arquivo do Kernel é guardado no HD na forma de um arquivo compactado.
Nas primeiras distribuições Linux, todos os drivers e outros componentes eram compilados diretamente nesse arquivo principal e você podia escolher os componentes a ativar na hora de compilar o Kernel. Se você habilitasse tudo, não teria problemas com nenhum dispositivo suportado, tudo iria funcionar facilmente. Mas, por outro lado, você teria um Kernel gigantesco, que rodaria muito devagar no seu 486 com 8 MB de RAM. Se, por outro lado, você compilasse um Kernel enxuto e esquecesse de habilitar o suporte a algum recurso necessário, teria que recompilar tudo de novo para ativá-lo. Como resultado disso, as distribuições passaram a incluir diversas opções de kernel, compiladas com opções diferentes. Você tinha então que escolher qual usar, de acordo com os componentes do micro.
Este problema foi resolvido durante o desenvolvimento do Kernel 2.0, através do suporte a módulos. Os módulos são peças independentes que podem ser ativadas ou desativadas com o sistema em uso. Do Kernel 2.2 (lançado em 1999) em diante, quase tudo pode ser compilado como módulo, o que tornou as coisas muito mais práticas e abriu as portas para os sistemas de detecção automática de hardware que são usados nas distribuições atuais.
Os módulos nada mais são do que arquivos, que são armazenados dentro da pasta "/lib/modules/versão_do_kernel". Veja que os módulos ficam organizados em pastas: a pasta "kernel/drivers/net/" contém drivers para placas de rede, a pasta "kernel/drivers/usb/" agrupa os que dão suporte dispositivos USB e assim por diante:

Na maioria dos casos, os módulos possuem nomes que dão uma idéia do dispositivo a que oferecem suporte. O "8139too.ko" dá suporte às placas de rede com o chipset Realtek 8139, o "sis900.ko" dá suporte às placas SiS 900, enquanto o "e100.ko" ativa as placas Intel E100, por exemplo. Se você fizer uma pesquisa pelo nome de um módulo específico no Google, vai quase sempre chegar à página do projeto ou a alguma página ou manual explicando o que ele faz.
Para ativar suporte a um certo dispositivo, você (ou o utilitário de detecção incluído no sistema) precisa apenas carregar o módulo referente a ele. O resto é feito pelo próprio Kernel, que se encarrega de ativar o dispositivo e criar um caminho de acesso para ele.
Cada vez mais, o trabalho de detecção e carregamentos dos módulos está passando a ser feito de forma automática pelas distribuições, através dos códigos de identificação incluídos nos próprios dispositivos. Uma placa de rede com chipset Realtek, por exemplo, retorna algo como "Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+". Com base nesses códigos, o sistema pode descobrir quais periféricos estão instalados e carregar os módulos apropriados, de forma automática. Você pode checar os códigos de identificação dos dispositivos instalados usando os comandos "lspci" e "lsusb".
Em casos em que você precisa carregar um módulo manualmente, é usado o comando "modprobe", seguido do módulo desejado, como em:
# modprobe ndiswrapper
Para descarregar um módulo, é usado o "modprobe -r", como em:
# modprobe -r ndiswrapper
Algumas distribuições oferecem uma opção de carregar módulos adicionais durante a instalação, justamente pensando nos raros casos onde você precisa de um determinado módulo para ativar a placa SCSI onde está instalado o HD para poder prosseguir com a instalação, por exemplo.
Os módulos são gerados durante a compilação do Kernel. Você não precisa se preocupar com isso se não quiser, pois as distribuições quase sempre incluem versões bem completas do kernel por padrão, mas, de qualquer forma, existe sempre a possibilidade de recompilar o kernel, mexendo nas opções e ativando ou desativando os módulos que quiser.
Na prática, a situação mais comum onde você precisa lidar com módulos é quando precisa instalar manualmente algum driver modificado ou proprietário, necessário para ativar algum dispositivo em particular. Infelizmente, isso é ainda relativamente comum ao usar componentes recém-lançados, ou em algumas configurações problemáticas, como em alguns notebooks com chipset SiS ou VIA.



23 respostas para “Linux: Entendendo o Kernel”
Otima postagem Morimoto!!
aguardando por proximas.
:-)
Adorei essa postagem sobre kernel. Eu estou curioso como é sua arquitetura completa, se são dividos em partes e quais as suas funções!
:D
Excelente artigo… Muito bom para leigos, e para não tão leigos assim. Só uma pequena correção no quarto parágrafo (comentes seria componentes não?)…
Mas como sempre, excelente trabalho!
Em uma distribuição, no momento da instalação o kernel é compilado conforme a configuração da máquina, se entendi bem.
Nas distros LiveCD o kernel não é compilado sendo utilizado o kernel com todos os modulos possíveis , este meu raciocínio está certo ??
Nas ditro "normais" e live cds o kernel já vem pré compilado, juntamente com todos os módulos possíveis. Ele (o kernel), já vem com os módulos essencias embutidos (como o suporte a ext3 por exemplo). O sistema de detecção se encarrega de carregar os módulos restantes necessários durante a instalação/carregamento do sistema.
Olá Morimoto,
Belo artigo, explica bem a mudança do Kernel para uso dos módulos e como isso tudo funciona …
Só fico triste por você nunca citar e fazer questão de ignorar a existência do projeto GNU. Sem ele não sabemos o que seria do "Linux" hoje em dia, mas mesmo assim você que tem o papel tão importante de espalhar conhecimento pra milhares de pessoas nunca fala dele, seja em livros ou arquivos.
Muita gente que te "segue" nem sabe o que é esse tal de GNU … E isso não é coisa só de puristas …
Abraços! =)
Faço côro com o Gilson Filho :
"Adorei essa postagem sobre kernel. Eu estou curioso como é sua arquitetura completa, se são dividos em partes e quais as suas funções!"
Marco Bócoli.
Parabéns, Ótimo post.
Ótimo post cada dia que passa o meu interesse pelo Linux aumenta mais, e o conhecimento que você passa é o combustível da chama do meu interesse.
Excelente artigo, venho parabenizar o Morimoto pela excelente divulgação técnica do Linux e seu indispensável Site que considero o melhor em Linux, aprendemos com os Mestres
Vida Longa Morimoto
Ótima postagem. Veio bem à calhar com meu momento onde estou instalando o Ubuntu em dual-boot no meu PC.
Tks man !
Sensacional este tópico. Direto ao ponto !
Agradeço, porém as dúvidas continuam. Talvez fosse necessário ter mais leitura anterior.
Valeu!
Muito bom o artigo, obrigado!
Agora entendo que para reconhecer meu chipset VIA vai ser um tormento!
Caros Marco e Gilson Filho,
Tentando em parte defender o Morimoto, a arquitetura do kernel em si é bastante complexa e é muito difícil realizar uma abordagem em um artigo como esse.
Normalmente, isto é coisa para anos de estudos.
O que normalmente se faz e conhecer um basicão e aprofundar em assuntos específicos.
Para vcs entenderem melhor, dêem uma olhada neste mapa interativo: http://www.makelinux.net/kernel_map
Recomendo a leitura do artigo: http://www.ibm.com/developerworks/linux/library/l-linux-kernel/
Caro eek,
isto é fácil! Basta usar o comando:
sudo lspci | grep VIA
Abraços,
Túlio Magno
Exelente artigo Marimoto, gostei muito das informaões descritas, mas me resta uma dúvida.
Estou trabalhando na compilação do kernel 2.6.26.5 e está aparecendo o seguinte erro quando marco a opção PCI SUPPORT em BUS OPTIONS:
drivers/pci/search.c: In function ‘pci_get_dev_by_id’:
drivers/pci/search.c:284: warning: passing argument 1 of ‘pci_dev_put’
discards qualifiers from pointer target type
Gostaria de saber como faço para corrigir esse problema? Estou usando o compilador GCC 3.4
E outra coisa, o que são os arquivos .o que estão nas pastas drivers/scsi por exemplo?
Grato a quem me ajudar!
Me desculpem pelo erro no português, só reparei quando publiquei meu comentário.
Eu sou novo no linux, o conheci a um ano, e minha primeira distro foi o Kurumin 4, depois disso já usei DSL, Puppy, Ubuntu e Basic Linux. Hoje tenho em meu PC o Kurumin 7 e o Puppy 2.17.
Me aventurei a compilar kernel e do inicio tive algumas dificuldades. Diversos erros de compilação, um deles foram por opções que marquei inadequadamente, outros foram por causa de incompatibilidade do meu compilador, já executei a 19ª tentativa de compilação e a maioria dos erros já foram corrigidos, só me restou o que postei acima.
Sempre usei o comando #make após o comando #make allnoconfig e #make menuconfig.
Isso mesmo, sempre usei o modo de texto para marcar as opções para serem compiladas.
Marquei a maioria das opções contidas, pois minha intenção é compilar um Kernel com suporte a vários dispositivos.
Nisso é que está a minha dúvida pois existe um monte de arquivos .o e .ko, como vi neste blog eles são os módulos do Kernel. Certo?
Só queria saber de antemão como faço para corrigir o erro que pedir anteriormente?
Obrigado a todos!
Ótimo post, gostaria de saber mais sobre o kernel.
Vou pesquisar sobre.
Muito bom!!! Deu pra explicar muita coisa. Por quê você não escreve um livro: "O Kernel do Linux"??
E quanto a história do linuz com "z"?
O "z" no "/boot/vmlinuz" surgiu por que o arquivo é compactado. Essa ideia surgiu com objetivo de acelerar o boot, lendo um arquivo menor no HD (que é lento) e em seguida rodando-o a partir da memória RAM (que é rápida).
ありがとう