FAQ do Kernelnewbies-Br
   
 
  1. Onde Começar?
  2. Onde eu obtenho a última versão do código fonte do kernel?
  3. Como funcionam as versões do kernel?
  4. O que é um patch?
  5. Como eu aplico um patch?
  6. Como eu compilo o kernel?
  7. O que são módulos do kernel?
  8. Como eu compilo um módulo?
  9. Por quê a instrução goto no kernel Linux é muito usada?
  10. O canal #kernelnewbies mudou de lugar?
  11. Quem eu posso encontrar no canal #kernelnewbies? E no #kernel-br?
  12. Como compilar o kernel para usar em máquinas SPARC?
01. Onde Começar?
Uma pergunta muito comum feita por novatos é "Eu baixei um enorme tar do kernel e agora eu quero ajudar, mas por onde devo começar?".

Poucos são aqueles que dominam o kernel por inteiro, os contribuintes se especializam em uma determinada parte do Kernel, então nós aconselhamos o mesmo, se você quer se especializar em TCP/IP não perca tempo olhando o código de Filesystem.

02. Onde eu obtenho a última versão do código fonte do kernel?

O primeiro site que hospeda o código fonte do Linux kernel é o servidor dedicado www.kernel.org Existem diversos "mirrors" deste site ao redor do mundo e links para cada país. Para acessar o mirror de um determinado país use http://www.CODE.kernel.org, onde CODE é o código apropriado de cada país. Por exemplo, br é o código do Brasil, deste modo o principal espelho (mirror) do país é o site www.br.kernel.org. Você pode baixar o fonte do kernel em ftp.br.kernel.org. Neste endereço você também encontra os pre-release patches das versões.

03. Como funcionam as versões do kernel?

O Linux distingue kernel estável do kernel em desenvolvimento através de um simples esquema de números. Cada versão é caracterizada por três números. Os dois primeros números indicam o número da versão e o terceiro número indica a release.

O que diferencia a série de desenvolvimento é que o segundo número é impar, e na série estável este número é par. Por exemplo, a série 2.4.xx é uma série estável, enquanto a série 2.5.xx é de desenvolvimento.

Atualmente a última versão estável do kernel é a 2.4.18, enquanto a de desenvolvimento é a 2.5.6.

04. O que é um patch?

Um arquivo patch é um arquivo texto em ASCII que contém as diferenças entre um código fonte original e um novo código, com o nome dos arquivos e o número das linhas onde estas diferenças ocorrem. Através do programa patch (para mais detalhes execute: man patch) aplica-se o patch na árvore do código fonte original do kernel.

05. Como eu aplico um patch?

Esta resposta depende de como o patch foi criado, especificamente de qual diretório o patch foi feito. Em geral os patches são feitos no diretório root da árvore (/usr/src/linux).

Por exemplo, você descompactou o kernel 2.4.17, e quer aplicar o patch-2.4.18.bz2, e o arquivo patch está no /usr/src, então faça:

  cd /usr/src/linux
  bzip2 -dc /usr/src/patch-2.4.18.bz2 | patch -p1 --dry-run

Nós usamos a opção --dry-run para checar se o patch irá ser aplicado corretamente, ou seja, mostra o resultado da aplicação do patch só que sem alterar nenhum arquivo.

A opção -p1, indica qual o ponto da árvore ele vai aplicar o patch.

Agora que nós já checamos que o patch deve ser aplicado corretamente, vamos aplicá-lo:

  bzip2 -dc /usr/src/patch-2.4.18.bz2 | patch -p1

Pronto, patch aplicado. Vale lembrar que os patches do kernel não são incrementais, ou seja, o patch-2.4.19-pre2 deve ser aplicado no topo da fonte da versão anterior, neste caso a 2.4.18.

Se você tem 2.4.19-pre1, você pode voltar para 2.4.18 através do "Reversing a patch". Simplesmente utilizando a opção -R do programa patch com o mesmo arquivo patch o qual você tenha aplicado. Para mais detalhes:

  man patch

06. Como eu compilo o kernel?

Este exemplo assume que você está instalando o kernel 2.4.17. Substitua pela versão que você está tentando instalar.

Baixe o fonte do ftp.br.kernel.org. Descompacte o arquivo no diretório /usr/src

  tar zxvf linux-2.4.17.tar.gz

Se você baixou o linux-2.4.17.tar.bz2, use

  bzip2 -dc linux-2.4.17.tar.bz2 | tar xvf -

Entre no diretório onde o kernel foi descompactado. Você deve rodar este comando para limpar todos os arquivos de configurações, arquivos objetos de alguma configuração anterior. Ele garante que a sua nova árvore está totalmente limpa de configurações anteriores. Este comando é recomendado quando você vai compilar pela primeira vez um kernel.

  make mrproper

Você terá que configurar o kernel para a máquina que você tem. Para isto use um dos comandos:

  1. make config: configuração na linha de comando
  2. make oldconfig: se você quiser manter o .config de versões anteriores
  3. make menuconfig: menu contruído com ncurses
  4. make xconfig: configuração em X-Windows baseado em TCL/TK

Agora, você precisa contruir as dependências

  make dep
  make clean

make clean limpa os todos os arquivos objetos e algumas outras coisas que outras configurações deixaram para trás. Para contruir agora a imagem do kernel:

  make bzImage

Quando este comando terminar, você tem que compilar os módulos que você configurou:

  make modules

Instale os módulos:

  make modules_install

Agora, copie a imagem contruída para /boot:

  cp ./arch/i386/boot/bzImage /boot/vmlinuz-2.4.17

Edite o arquivo /etc/lilo.conf e acrescente estas linhas:

  image = /boot/vmlinuz-2.4.17
  label = 2.4.17
  root=/dev/xxx

Onde xxx é a sua partição /, algo como /dev/hda1.

Copie esta linha da sua outra imagem configurada no /etc/lilo.conf. Para terminar rode:

  /sbin/lilo

Agora reinicialize a máquina.

07. O que são módulos do kernel?

Módulos são partes do kernel que não precisam estar sempre em memória. Eles podem ser carregados quando se fazem necessários pelo kernel e ausentes no restante do tempo. Na maioria das vezes são drivers para dispositivos. Imagine por exemplo os drivers para o seu CD-ROM, placa de rede ou som, eles não precisam estar sempre em memória e assim ocupando espaço que poderia estar sendo utilizado por alguma aplicação. Em vez disso, eles podem ser compilados como módulos do kernel, ou seja, só vão ser carregados para memória quando você acessar o dispositivo, e removidos quando não for mais necessário. Para isto o Linux executa periodicamente, via crontab, o comando /sbin/rmmod -as, o qual tenta remover os módulos que não estão mais sendo usandos.

08. Como eu compilo um módulo?

Em geral, um módulo é compilado assim:
  gcc -c -o modulo.o modulo.c -D__KERNEL__ -DMODULE -DLINUX -O2 -Wall -I/usr/src/linux/include

Você tem que usar a mesma versão do gcc que você compilou o seu kernel. Você tem que especificar as flags -D__KERNEL__ -DMODULE -DLINUX -O2. Esteja seguro de que está usando o mesmo kernel headers que você compilou o kernel e que o PATH do -I está correto.

09. Por quê a instrução goto no kernel Linux é muito usada?

Goto é uma instrução de controle de fluxo, ela pode realizar saltos para locais específicos. Algumas formas de escrita do código resultam em executáveis mais rapidos. Desenvolvedores do kernel recorrem ao uso do goto em busca de velocidade.

O goto, muitas vezes também pode tornar o código mais claro (sim, goto também pode ser bom em alguns casos :), principalmente no caso de tratamento de erro. Quando uma determinada função obtém para si vários recursos (aloca memória, obtém um lock, por exemplo), e realiza operações que podem resuultar em erro, certas operações devem ser sempre realizadas, ou então realizadas caso ocorra um erro em qualquer ponto. Se a função obtém um lock que é "largado" antes da função retornar, o lock deve ser "largado" mesmo caso ocorra algum erro.

Este é um exemplo, retirado de drivers/net/ppp_generic.c:

static int
p_connect_channel(struct channel *pch, int unit)
{
        struct ppp *ppp;
        int ret = -ENXIO;
        int hdrlen;

        down(&all_ppp_sem);
        ppp = ppp_find_unit(unit);
        if (ppp == 0)
                goto out;
        write_lock_bh(&pch->upl);
        ret = -EINVAL;
        if (pch->ppp != 0)
                goto outl;

	/* ele faz várias outras operações aqui, removidas
	   propositalmente para o exemplo ficar mais simples
	 */
        ret = 0;

 outl:  
        write_unlock_bh(&pch->upl);
 out:   
        up(&all_ppp_sem);
        return ret;
}

Neste exemplo, o goto é utilizado para que certas operações sejam sempre desfeitas, mesmo no caso de ocorrer um erro. O semáforo sempre será "largado", independentemente da ocorrência de um erro. O mesmo acontece com write_unlock_bh() que sempre é chamado, caso um erro ocorra após write_lock_bh() ser chamado.

Outro exemplo, retirado de drivers/net/ppp_synctty.c:

static int
ppp_sync_open(struct tty_struct *tty)
{
        struct syncppp *ap;
        int err;

        MOD_INC_USE_COUNT;
        ap = kmalloc(sizeof(*ap), GFP_KERNEL);
        err = -ENOMEM;
        if (ap == 0)
                goto out;

        /* Aqui, várias operações foram removidas também,
           para simplificar o exemplo
         */
        err = ppp_register_channel(&ap->chan);
        if (err)
                goto out_free;

        tty->disc_data = ap;

        return 0;

 out_free:
        kfree(ap);
 out:   
        MOD_DEC_USE_COUNT;
        return err;
}

Neste caso, há certas operações que são executadas apenas quando ocorre um erro. Caso ocorra um erro, a memória alocada previamente não será usada, e deve ser liberada. Além disso, MOD_DEC_USE_COUNT também é chamado, quando ocorre um erro, assim, caso o dispositivo não seja aberto, o "use count" do módulo não será incrementado.

Nos dois casos, há a vantagem de eficiência do código, já que o fluxo "normal" do código não tem o tratamento de erros "enfiado" no meio, e sim em uma região separada da memória (aí [resumidamente], o código "principal" fica menor, e aproveita melhor o cache de memória). Além disso, há a vantagem da legibilidade e "mantebilidade" do código, é mais simples de enxergar que parte da função faz o que, e enxergar o que acontece caso ocorra um erro (o que pode ocorrer em várias partes diferentes da função), com a "parte principal" separada do tratamento de erros. Fazendo uma comparação grosseira, tem mais ou menos a mesma utilidade que a utilização de 'try', 'finally' e 'except' (ou 'catch') disponíveis em algumas linguagens de programação.

10. O canal #kernelnewbies mudou de lugar?

Sim. Devido a divergências políticas, o canal #kernelnewbies agora está oficialmente na rede www.oftc.net. Mais informações em www.kernelnewbies.org. Por enquanto, o kernel-br continua na rede www.freenode.net.

11. Quem eu posso encontrar no canal #kernelnewbies? E no #kernel-br?

#kernelnewbies
 
Nome Real Nick Responsabilidade no Kernel
Arjan van de Ven arjan kHTTPd,Powertweak
Andre Hedrick ata IDE
Jens Axboe axboe Camada de CDROM/DVD
Ralf Baechle Bacchus Linux-MIPS
Ben LaHaise bcrl Gerenciamento de memória
Dave Jones davej Powertweak, random hacks
Erik Mouw erikm ArmLinux, SA1100-Linux
f00f f00f Larting, jumping, and logging
Christoph Hellwig hch Filesystems, kbuild, kernel cleanup
Jeff Dike jdike User Mode Linux
Jeff Garzik jgarzik Network drivers, PCI, kernel cleanup
Greg Kroah kroah USB
lxrbot lxrbot O canal oracle.
Thiago Rondon maluco Random hacking
Marcelo W. Tosatti marcelo drbd, Alta Disponibilidade, RPM do kernel da Conectiva
John Levon movement oprofile, random minor hacking
Fabio O. Leite olive drbd, Alta Disponibiliade, heartbeat
Juan Quintela quintela Gerenciamento de Memória
Rik van Riel riel Gerenciamento de Memória
Russell King rmk Linux/ARM
Tigran Aivazian tigran Random hacking
Steve Dodd TC NTFS rewrite, random hacking
Daniel Phillips phillips TUX2 filesystem, ext2 improvement, memory management hacking
 
#kernel-br
 
Edison Junior EFJ
Andrea Fabiana fabiana
Guilherme Polo polo
Thobias Trevisan thobias
Eduardo Habkost boto
Vinícius Líbera dm1tri
Caio Begotti caio1982
Lucio F. Maciel gcc_
José Alves R_ealitY
Fábio Minami sussumo
Wellington Castello nerdwell

12. Como compilar o kernel para usar em máquinas SPARC?

O procedimento para instalar o kernel é muito parecido com o de uma arquitetura x86. Mas mesmo assim vou listar todos os passos.

  1. baixe o kernel que você deseja em http://www.kernel.org
  2. descompacte o kernel no /usr/src, faco o link do linux para o novo dir (ln -sf /usr/src/linux-x.y.zz linux)
  3. entre no diretório /usr/src/linux
  4. rode os comandos default make mrproper, make menuconfig, make dep, make clean
  5. agora aqui temos a primeira diferença, para gerar a imagem do kernel nós não utilizamos o make bzImage nem o make zImage, para gerar a image utilizamos o comando make vmlinux. Isto é devido ao fato de não existir tamanho limite em SPARC, deste modo não precisamos comprimir a imagem do kernel.
  6. próxima diferença, a imagem gerada pelo comando anterior fica no diretório raiz do fonte, /usr/src/linux, assim rode o comando cp vmlinux /boot/vmlinux-x.yy.zz
  7. make modules && make modules_install

Em SPARC existem um loader diferente, ele é o SILO (Sparc Improved boot LOader). Note que o SILO é mais poderoso que o lilo, assim você não precisa rodar o comando silo toda vez que você mudar o arquivo /etc/silo.conf. SILO consegue ler sistemas de arquivos ext2, assim ele pode ler o silo.conf durante o startup para descobrir qual o kernel você quer 'bootar'. Isto é diferente do lilo, onde ele não consegue ler um sistema de arquivos e precisa ter em seu map loader um offset físico do disco para carregar as imagens.

Se voce já tiver o silo instalado na sua máquina, apenas acrescente uma entrada no arquivo /etc/silo.conf:

Finalmente reboot ;-) e para saber mais, visite:

http://www.sparc.org/ http://silo.sourceforge.net/
http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/SPARC-HOWTO.html http://shamir.ebizlab.hit.bme.hu/docs/os/Linux/sparc/faq.html
http://www.ultralinux.org/faq.html


© 2001-2002 by the people in #kernel-br - Webdesign by Caio Begotti (caio1982) & Fábio Minami (sussumo)