Um guia atualizado de como compilar um kernel personalizado

Um guia atualizado de como compilar um kernel personalizado

Em um post anterior falei sobre como atualizar o kernel no Debian, usando um dos kernels pré-compilados disponíveis via apt-get, passos que são bem similares também em outras distribuições, já que quase todo o trabalho é feito pelo gerenciador de pacotes.

Além de instalar um dos pacotes com versões pré-compiladas do kernel, é possível também gerar seus próprios pacotes, baixando o código-fonte e compilando manualmente. Em situações normais, não existe nenhum bom motivo para fazer isso (já que os pacotes pré-compilados são atualizados com frequência e, quase sempre, são bastante otimizados), mas conhecer as opções do kernel é uma boa maneira de aprender mais sobre os recursos do sistema. A compilação manual permite também que você teste patches e recursos experimentais, que não fazem parte dos pacotes disponibilizados pelas distribuições.

O primeiro passo é, naturalmente, obter o código-fonte do kernel, que iremos compilar. Se você quer apenas criar um kernel personalizado, pode usar como base o código-fonte do próprio kernel incluído na sua distribuição.

No caso do Debian (e derivados), procure pela versão do pacote “linux-source” correspondente à versão do kernel em uso (ou da versão que deseja compilar), como em:

# apt-get install linux-source-2.6.26

O pacote simplesmente copiará o arquivo “linux-source-2.6.26.tar.bz2” (com o código-fonte completo do kernel) para a pasta “/usr/src”. Para concluir a instalação, é necessário acessar a pasta e descompactar o arquivo:

# cd /usr/src
# tar -jxvf linux-source-2.6.26.tar.bz2

É sempre muito mais fácil usar como base o código-fonte e a configuração do kernel que está instalado na sua máquina, com todos os patches e modificações. Assim você começa com uma configuração que está funcionando e faz apenas as alterações desejadas, com uma possibilidade muito menor de surgirem problemas.

Depois de pegar um pouco de prática, você pode se aventurar a baixar uma versão “crua” da última versão do kernel no http://www.kernel.org e fazer uma experiência começando do zero.

Salve o arquivo no diretório “/usr/src/”, onde por padrão ficam armazenados os fontes do kernel e descompacte-o usando o “tar -jxvf” ou “tar -zxvf”. Não se assuste, o arquivo com o fonte do kernel é mesmo grande, quase 50 MB (compactado em .tar.gz) nas versões recentes.

Em ambos os casos, é necessário instalar também o gcc, make, libc6-dev e outros pacotes de desenvolvimento necessários para fazer a compilação. No Debian você pode instalá-los através dos pacotes “build-essential” e “kernel-package”:

# apt-get install build-essential kernel-package

Com tudo pronto, acesse a pasta com o código-fonte, como em:

# cd /usr/src/linux-source-2.6.26

O primeiro passo é definir os componentes que serão incluídos no novo kernel, o que é feito usando o xconfig, uma ferramenta de configuração que ajuda a selecionar as opções disponíveis e gerar um arquivo de texto (o “.config”), que será usado durante a compilação. Ele é executado através do comando:

# make xconfig

Antigamente (na época do kernel 2.4) o make xconfig abria um utilitário bastante espartano, baseado na biblioteca tk, mas no kernel 2.6 o “make xconfig” chama o Qconf, um utilitário mais amigável, criado usando a biblioteca QT.

Da primeira vez que tentar abrí-lo, você provavelmente receberá uma mensagem de erro:

* Unable to find the QT3 installation. Please make sure that
* the QT3 development package is correctly installed and
* either install pkg-config or set the QTDIR environment
* variable to the correct location.

Ela é mostrada quando a biblioteca de desenvolvimento (necessária para compilar e exibir a interface) não está instalada. Para resolver o problema, instale o pacote “libqt3-mt-dev” usando o gerenciador de pacotes:

# apt-get install libqt3-mt-dev

Mesmo sendo um aplicativo gráfico e exibindo os textos de descrição para cada opção, o Qconf é bastante intimidador. Um conselho geral para reduzir a possibilidade de erros é começar carregando o arquivo com a configuração atual do kernel. Fazendo isso, você pode examinar as opções e mudar apenas o que deseja ativar ou desativar, sem ter que se preocupar com cada uma das opções.

Por padrão, o arquivo com a configuração do kernel vai sempre na pasta “/boot” (você encontrará um arquivo para cada kernel instalado, com o prefixo “config”, como em “/boot/config-2.6.26-2-686”. Você precisa apenas carregar o arquivo usando a opção “File > Load” do Qconf.

kernel_html_19a3038a

De volta à configuração, as opções estão divididas em categorias, com uma descrição resumida de cada opção no nível mais baixo. A esmagadora maioria das opções está relacionada justamente com suporte a dispositivos.

Para cada módulo existem três opções: compilar no executável principal do kernel (built-in, representado por um símbolo de visto no no Qconf), compilar como módulo (representado com um ponto) ou desativar.

Compilar o componente na forma de um módulo faz com que ele seja carregado apenas quando necessário, sem inchar o kernel. Esta é a opção ideal para todos os componentes que quiser manter, mas não tem certeza se serão usados frequentemente.

Coisas como o suporte à sua placa de rede, som, suporte a gerenciamento de energia para o seu notebook podem ser compilados diretamente no kernel. Mas, não exagere, pois um kernel muito grande aumentará o tempo de boot da máquina e terá um desempenho um pouco inferior. O ideal é compilar tudo o que não for essencial como módulo, assim como fazem as principais distribuições, de forma que o executável principal não fique com muito mais do que 2 ou 2.5 MB.

Uma ressalva importante é que você sempre deve adicionar o suporte ao sistema de arquivos no qual a partição raiz do sistema está formatada (EXT3, EXT4, XFS, etc.) diretamente no kernel e não como módulo, caso contrário você cria um problema do tipo o ovo e a galinha: o kernel precisa carregar o módulo referente ao sistema de arquivos para acessar a partição, mas precisa acessar a partição para carregar o módulo. No final das contas, você acaba com um kernel panic. O mesmo se aplica aos módulos relacionados com o suporte à controladora SATA/IDE onde o HD está instalado.

Um remendo para este tipo de situação é criar um initrd (veja a dica a seguir) contendo o módulo necessário. O initrd é carregado diretamente pelo gerenciador de boot, o que permite que o kernel tenha acesso ao módulo antes de ter acesso à partição. Ele é um arquivo compactado, contendo uma imagem de sistema que vai na pasta “/boot”. O arquivo initrd é carregado automaticamente sempre que especificado na configuração do gerenciador de boot.

Os módulos com o suporte aos sistemas de arquivos principais (EXT4, XFS, JFS, etc.) estão logo no diretório principal da seção “File systems” do Qconf.

O suporte a sistemas de arquivos menos comuns estão nos subdiretórios. Você deve compilar o suporte a EXT4 diretamente no kernel se a partição raiz do sistema está formatada neste sistema de arquivos, mas pode compilar como módulo se a partição raiz está formatada em EXT3 e apenas a partição home está formatada em EXT4, por exemplo.

O suporte a sistemas de arquivos não nativos, como no caso do suporte a FAT e NTFS pode ser sempre compilado como módulo, enquanto o suporte a sistemas menos comuns, que você nunca vai usar (Minix e Amiga, por exemplo) pode ser desabilitado.

Para ativar o suporte a ACPI, por exemplo, acesse a categoria “Power management options” e ative o “ACPI Support”, junto com os módulos “AC Adapter” (usado em micros desktop ou notebooks ligados na tomada) e “Battery” (que monitora o estado da bateria do notebook e ativa os recursos de economia de energia suportados).

Os outros módulos adicionam mais funções úteis: a opção “Fan” permite diminuir a rotação dos coolers, o módulo “Processor” permite diminuir a frequência do processador para economizar energia, e assim por diante.

kernel_html_8b5ace4

Quase todas as opções possuem descrições, mas é preciso ter bons conhecimentos de hardware para entender a função da maioria delas. A pasta “Documentation/”, dentro da pasta com o código-fonte, contém descrições bem mais completas sobre a função de cada módulo. Os textos falam mais sobre os componentes e recursos suportados por cada módulo do que sobre programação, por isso também são muito úteis para quem está estudando sobre hardware e suporte a dispositivos no Linux.

A opção mais importante com relação ao desempenho é indicar qual processador está sendo utilizado. Isto fará com que o kernel seja compilado com otimizações para a arquitetura, o que pode resultar em um ganho de desempenho de até 10% em alguns casos. Para isto, acesse a seção “Processador Type and Features” na tela principal do xconfig e clique na opção “Processador family”.

A opção 386 gera um código que funciona em qualquer PC, desde um 386 até um Pentium 4 ou Athlon X2. A opção 486 gera algumas otimizações para a arquitetura pipelinizada do 486, mas mantendo a compatibilidade com todos os processadores daí em diante.

A opção “586/K5/5×68/6×86/6x86MX” é a mais usada, pois gera um kernel compatível com todos os processadores a partir do Pentium, com um nível de otimização razoável. Acima desta temos otimizações específicas para cada família de processadores, que garantirão um nível máximo de desempenho, em troca da perda de compatibilidade com os demais. Compilar o kernel com otimizações para a plataforma Core irá torná-lo incompatível com máquinas baseadas em outras famílias de processadores, mas, naturalmente, isso não é um problema se você só utilizará este novo kernel na sua própria máquina.

Na verdade, o nível de otimização do kernel tem um efeito pequeno sobre o desempenho geral da máquina na maioria dos casos, pois o kernel em si representa apenas uma pequena parte do sistema. Sobre ele temos pesos pesados como o X, KDE e o OpenOffice. Em geral, otimizar o kernel para o seu processador, sem mexer nos demais programas, resulta num ganho médio inferior a 2%.

Uma opção importante hoje em dia é ativar o suporte a SMP (a opção “Symmetric multi-processing support”, dentro da seção “Processador Type and Features”), necessário para que o sistema consiga tirar proveito de processadores dual-core ou quad-core.

Ativar o suporte a multiprocessamento não faz com que o kernel gerado deixe de ser compatível com máquinas equipadas com processadores single-core (o kernel é capaz de detectar o número de núcleos disponíveis durante o boot), apenas faz com que o desempenho seja levemente inferior, já que o sistema continua com o código necessário carregado na memória. Para ativar, habilite (ainda dentro da seção “Processador Type and Features”) a opção: “Symmetric multi-processing support”.

Depois de terminar, não se esqueça de clicar no “Save” (para salvar as configurações, gerando o arquivo “.config”, dentro da pasta com o código-fonte). Em seguida, feche o Qconf para voltar ao terminal.

Além do xconfig, você pode utilizar também o menuconfig, que oferece basicamente as mesmas opções, mas numa interface de modo texto. Ele serve como segunda opção caso o xconfig (que no kernel 2.6 depende da biblioteca Qt) esteja indisponível. Para chamá-lo, use o comando:

# make menuconfig

Tanto faz utilizar o xconfig ou o menuconfig, pois os dois fazem exatamente a mesma coisa: mostrar as opções disponíveis e salvar a configuração no final do processo, gerando o arquivo “.config” que orienta o sistema durante a fase de compilação.

Existe ainda uma quarta opção, ainda mais espartana: o “make config”, que chama um programa de modo texto que simplesmente vai perguntando um a um quais componentes devem ser incluídos (e exige uma boa dose de paciência… :).

Depois de salvar a configuração, o próximo passo é fazer a compilação propriamente dita, gerando o executável do novo kernel e em seguida os módulos, o que é feito com três comandos.

O primeiro é o “make clean”, que serve para limpar a casa, removendo restos de compilações anteriores e módulos desnecessários.

# make clean

Ao executar o “make clean”, todos os módulos e componentes anteriormente compilados são removidos, fazendo com que a compilação seja realmente feita a partir do zero. Se você já compilou o kernel anteriormente e fez agora apenas uma pequena modificação (como ativar um módulo adicional), pode omitir o “make clean”, de forma que os objetos gerados na compilação anterior sejam aproveitados e a compilação seja muito mais rápida.

O próximo passo é o “make” que compila o executável principal do kernel, o arquivo que vai na pasta /boot. O tempo varia de acordo com a velocidade do processador, mas é sempre relativamente rápido, já que estamos falando de um executável com cerca de 2 MB. Em um PC atual, demora poucos minutos.

# make

No final do processo de compilação você verá um relatório informando o tamanho da imagem (importante, já que o tamanho do executável do kernel influencia o tempo de boot e o consumo de memória) gerada, como em:

Setup is 12444 bytes (padded to 12800 bytes).
System is 1526 kB
CRC b148216f
Kernel: arch/x86/boot/bzImage is ready (#1)

Em máquinas com processadores dual-core, você pode reduzir o tempo de compilação usando a opção “-j4”, que faz com que o make processe 4 módulos de cada vez, ao invés de apenas um como faria por padrão. Isto faz com que o segundo processador realmente fique ocupado, reduzindo em até 40% o tempo de compilação. Neste caso, o comando fica:

# make -j4

Este comando também pode ser utilizado em máquinas com apenas um processador (ou com um Pentium 4 com HT), mas neste caso o ganho de performance é bem menor. Geralmente você terá melhores resultados usando a opção “-j2” (apenas dois módulos por vez, ao invés de quatro).

Depois de compilar o executável principal, temos o “make modules”, que conclui o trabalho, compilando todos os componentes marcados como módulos. Assim como no comando anterior, você pode acrescentar o “-j4” ou “-j2” para reduzir o tempo de compilação, como em:

# make -j4 modules

Concluída a compilação, falta apenas copiar os arquivos e fazer a configuração do gerenciador de boot.

O executável principal do kernel é gravado no arquivo “arch/i386/boot/bzImage”, dentro do diretório de compilação. É necessário copiá-lo manualmente para a pasta “/boot”. Aproveite para renomear o arquivo, incluindo o número da versão:

# cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.26-1

Além do arquivo principal, é necessário instalar também os módulos, que são copiados para um diretório na pasta “/lib/modules” (criado automaticamente) correspondente à versão do kernel, como em “/lib/modules/2.6.26”. Para isto, use o:

# make modules_install

Um passo que pode ou não ser necessário, de acordo com o conjunto de componentes que você incluiu diretamente no kernel é a geração do arquivo initrd, que inclui os módulos necessários durante o início do boot que não foram compilados no executável principal.

Para gerá-lo, você precisa do “mkinitramfs”, que faz parte do pacote “initramfs-tools”. Ele substituiu o Yaird, usado em distribuições anteriores e pode ser instalado usando o gerenciador de pacotes, como em:

# apt-get install initramfs-tools

Com ele instalado, você pode gerar o initrd usando o comando:

# mkinitramfs -o /boot/initrd.img-2.6.26 2.6.26

… onde o “2.6.26” é a versão do kernel que foi compilada e o “/boot/initrd.img-2.6.26” é o arquivo que será gerado. É importante seguir essa nomenclatura (/boot/initrd.img-versão) ao definir o nome do arquivo, para que ele seja encontrado pelo script de atualização do grub.

Com isso, fica faltando apenas atualizar a configuração do gerenciador de boot, o que pode ser feito automaticamente rodando o:

# update-grub

Você pode também fazer a configuração manualmente, adicionando uma nova seção no arquivo “/boot/grub/menu.lst”, indicando a localização do executável do novo kernel e (caso usado) do arquivo initrd, como em:

title Kernel 2.6.26
root (hd0,2)
kernel /boot/vmlinuz-2.6.26 root=/dev/sda3 ro quiet
initrd /boot/initrd.img-2.6.26

Não remova a seção referente ao kernel antigo, pois você pode ainda precisar dele em caso de problemas de boot com o novo. Como a configuração do kernel inclui um volume muito grande de opções, é muito fácil desativar alguma função essencial (como o suporte à controladora SATA da placa-mãe, por exemplo, onde o HD está instalado) e ficar assim com um kernel inoperante. Nesses casos, basta reiniciar usando o kernel antigo e tentar novamente.

Sobre o Autor

Redes Sociais:

Deixe seu comentário

X