Guia de desenvolvimento de kernel Linux

Neste livro vamos incorporar textos que explicam como desenvolver para o kernel Linux. O Dougsland tem texto de http://wiki.tchelinux.org/index.php?title=Kernel que pode encaixar bem aqui e com certeza vamos encontrar, traduzir e escrever mais.

Ferramentas de Trabalho no Kernel

Ao trabalhar com uma base de código fonte tão grande quanto o kernel, certamente é de grande valia ter ferramentas que ajudem a entender como as peças se encaixam. Essa página tem como objetivo fornecer indicações para as ferramentas mais comumente utilizadas para tornar as suas primeiras incursões nas terras do kernel tão produtivas quanto possível.

Editando os Arquivos Fonte do Kernel

Talvez a ferramenta mais importante é um bom editor de texto. As escolhas mais populares emacs e qualquer clone do vi, vim são as opções mais amplamente utilizadas atualmente. Geralmente, os editores de texto escritos para programadores são programáveis e tem características tais como colorização de sintaxe, ocultação de texto, casamento de chaves, e integração fácil com ferramentas de gerenciamento de código fonte, tais como make(1), cvs(1), reformatação de texto, pesquisa em páginas de manual, e mais.

Download

Uma vez que você tenha escolhido um editor particular, você irá precisar fazer o download da árvore de desenvolvimento (source tree) do kernel com a qual vc quer trabalhar. Existem diferentes possibilidades à disposição.

Gerenciamento do código fonte do Kernel com o git

Se você quiser obter a última versão do código fonte do kernel, você irá precisar do git. Você pode obtê-lo aqui.

Existem ótimos Guia para o GIT em inglês (aguarde, em breve versões em portugues):

Arquivos tar com o Kernel

A maneira alternativa, mais "clássica", para fazer o download da árvore do kernel é baixar um arquivo compactado diretamente do site http://kernel.org.

Ajuda na Navegação

Agora você está pronto para editar o código fonte do kernel ou simplesmente navegar nele para aprender. Aonde começar? Uma vez que você comece a ler o código fonte você vai precisar várias vezes procurar a declaração ou definição dessa ou daquela estrutura de dados, macro ou função em particular. A opção mais básica é fazer isso usando uma combinação dos comandos `grep` (ou `egrep`) e
`find`;

  1. find . -exec grep --with-filename minhafuncao '{}' \;

Uma outra maneira é:

  1. find . -name '*.[chS]' | xargs egrep -n "minhaexpressaoregular";

Se você tiver o GNU grep (como virtualmente todas as distribuições de Linux tem) então você pode tirar vantagem da flag "recursiva":

  1. egrep -r --include "*.[chS]" "minhaexpressaoregular" .

Acrescente "-w" à linha de comando para evitar pegar palavras nas quais sua busca seja uma substring.

O comando acima procura no diretório corrente [e em todos os subdiretórios] por arquivos que terminem em .c, .h ou .S, e executa o egrem em cada um deles procurando pelo padrão "minhaexpressaoregular". Você pode substituir "minhaexpressaoregular" por expressões regulares mais complexas ;).

A maneira mais utilizada de navegar no código do linux envolve utilizar o
ctags. Dentro da árvore do kernel execute:

  1. make tags

O comando acima irá criar o arquivo tags que indexa estruturas, funções, variáveis do kernel.

Para os usuários do vim, após executar o comando acima, basta executar:

  1. :set tags=/usr/src/linux/tags

Após especificar qual o arquivo de tags, no vim basta colocar o cursor sobre a
palavra/símbolo e pressionar Ctrl + ] para ir até a definição
e Ctrl + t para voltar ao ponto original.

Para ir diretamente para uma tag digite:

  1. vim -t tag

ou, dentro do vim
  1. :tag tag

Para mostrar as definições semelhantes digite no modo de comando

  1. :ts

Para usuários do emacs, após executar o comando (note a caixa alta no nome TAGS)

  1. make TAGS

dentro do emacs digite
  1. M-x visit-tags-table

e informe onde se localiza o arquivo de tags.

Para ir para uma definição dentro do emacs, mova o cursor até a palavra e digite:

  1. M-.

Para ir para a próxima definição:
  1. C-u M-.

Para voltar à definição anterior digite:
  1. M-*

Para ver a lista de todas as definições que contém uma determinada expressão digite:
  1. M-x tags-apropos

e informe a tag que deseja.

Ferramentas de Indexação para Navegação na Internet

Enquanto essa abordagem funciona, outras ferramentas permitem que você indexe toda a árvore do kernel para facilitar a navegação no código fonte. Isso facilita muito na hora de encontrar a localização das coisas no código e permite que você encontre rapidamente as declarações/definições de estruturas de dados desconhecidas.

Guia rápido para o GIT

Este documento é um pequeno guia introdutório para operações básicas usando o GIT. A maioria das características são apresentadas em comparação com sistemas de controle de versão não distribuídos populares como o CVS e o Subversion.

Características

Introdução

O GIT é um sistema de controle de versão distribuído. Não há um repositório central, e cada desenvolvedor tem repositórios "particulares" na própria máquina onde está trabalhando. Qualquer um que tenha acesso a um repositório pode criar uma cópia exatamente igual, com todas as informações que o repositório original continha. Todas as cópias de repositórios são equivalentes entre si em funcionalidade.

Para facilitar a compreensão de quem já conhece outros sistemas de controle de versão, farei várias comparações do GIT com sistemas convencionais como o CVS e o Subversion, no texto abaixo, me referindo a eles como "CVS/SVN".

Muitos repositórios

Ao contrário de CVS/SVN, no git não há diferença entre "repositório" e um "checkout" (chamado "working copy" no Subversion). Para obter o código de um repositório, você faz um clone de um repositório (uma cópia completa) na sua máquina.

"Commite" à vontade

No CVS/SVN, quando você fez checkout de um repositório remoto, o comando
"commit" pergunta a sua mensagem de log e envia as modificações para o servidor imediatamente. As ações de documentar e publicar suas modificações são inseparáveis.

No GIT, como você possui um repositório completo na sua máquina, você pode fazer commits à vontade no seu clone, e só publicar ou enviar essas informações para um servidor (se houver) quando quiser. Você pode fazer commits menores e mais frequentes, mesmo quando ainda está testando o seu código, pois você sabe que não vai estar commitando código não testado num repositório central.

Branches

Cada repositório GIT pode conter vários branches. Alguns são especialmente interessantes porque são criados por default e comumente utilizados.

master

Geralmente todo repositório tem um branch chamado "master", que
geralmente é o branch principal do repositório (semelhante ao "trunk"
no SVN e a HEAD no CVS).

O "master" é criado por default quando um repositório é criado (git-init-db), e também quando é feito um clone (git-clone). A não ser que você faça questão de trabalhar com vários branches, em geral você vai trabalhar sempre no branch master do seu repositório.

origin

Nota: o parágrafo abaixo não se aplica mais, nas versões mais recentes do git. É necessário revisá-lo.

O branch "origin" é criado automaticamente quando é feito um clone
de outro repositório. Ele é utilizado para manter uma cópia do
repositório "original" quando você tem um clone de um repositório e
quer baixar modificações novas do repositório de onde você fez clone.
Apesar do GIT não impedir você de fazê-lo, é uma má idéia fazer
commits no branch "origin". A sua função é manter uma cópia de um
repositório externo, e commits nesse repositório irão confundir o
git-fetch (a ferramenta que busca modificações novas do repositório
original).

Logo, para tornar o seu uso do GIT mais agradável, siga a seguinte regra: Nunca faça commits no branch origin.

HEAD

O HEAD não é um branch propriamente dito, mas é como um ponteiro
para o "branch atual". O "branch atual" é o branch onde você está
trabalhando no momento, onde seus commits serão colocados e é o
branch default para a maioria das operações.

Quando quiser trabalhar em outro branch, você pode trocar o branch
atual com o comando git-checkout.

Comandos básicos

Clonando um repositório

git-clone <repositorio>

Este comando irá criar um repositório que contém uma cópia do
repositório original. O clone criado vai conter os branches do
repositório original, mais um branch chamado "origin".

Criando um repositório local

git-init-db

Este comando irá criar um repositório vazio, ainda sem nenhum commit,
apenas com um branch chamado "master".

Commits e log

Commitando

Para commitar as suas modificações no branch atual (HEAD):

git-commit -a [-s]

Usar o parâmetro -s é opcional, mas recomendável. Ele adiciona
uma linha "Signed-off-by" na sua mensagem de commit.
O parâmetro -a serve para simplificar algumas coisas. Caso queira
entender melhor o porquê, procure por "index file" na documentação
do GIT.
Caso arquivos tenham sido criados ou removidos, utilize
os commandos git-add e git-rm para adicioná-los e removê-los,

antes do commit.

Jogando fora modificações não commitadas

git-checkout -f

Todas as modificações que não foram commitadas serão descartadas, e
os arquivos serão revertidos para a versão do branch atual (HEAD).

Vendo commits anteriores

Para ver o log de commits de um branch:

git-log [<branch>]

Caso omitido, o log do branch atual (HEAD) será mostrado.
Para ver o que mudou em cada commit:

git-whatchanged [-p]

Com o parâmetro -p, um "diff" das modificações é mostrado. Sem
o parâmetro, apenas os nomes dos arquivos adicionados modificados e
removidos são mostrados.

Entendendo o estado atual do repositório

Para entender melhor o que vai acontecer caso git-commit
seja executado, você pode observar a saída de:

git-status

Trabalhando com branches

Listando os branches

git-branch

O branch atual (HEAD) é marcado com um asterisco, na lista.

Trocando de branch

Para mover para outro branch, para observar o código em um branch,
modificar e commitar no branch:

git-checkout <branch>

Nota: se houver modificações não "commitadas" no branch atual,
o git-checkout pode falhar. Caso queira guardá-las, commite as
modificações no branch atual (git-commit), ou jogue fora as
modificações com o comando git-checkout -f.

Criando branches

Para criar um branch:

git-branch <branch> [<origem>]

O branch criado será uma cópia de origem. Caso não seja especificado,
vai ser uma cópia do branch atual (HEAD).

Para criar um branch, e ao mesmo tempo apontar o "branch atual" (HEAD)
para o branch criado.

git-checkout -b <newbranch> [<origem>]

O comando acima é equivalente a um git-branch seguido de git-checkout.

Veja também

Mercurial

Autor: Matt Mackall
Página: http://www.selenic.com/mercurial/
Licença: GPLv2
Plataformas suportadas: Linux, *BSD, Mac OS, Solaris, Windows

Mercurial é um sistema para gerenciamento de versões distribuído utilizado por alguns subsistemas do kernel e projetos opensource.

Todos os comandos começam com hg, uma referência ao elemento químico mercúrio

Instalação:

Fedora:
shell> sudo yum install mercurial

Debian/Ubuntu/Kubuntu:
shell> sudo apt-get install mercurial

Principais Comandos:

   clone, commit, status, add, remove, diff, extdiff

Clone:

Cria uma cópia de repositório em um diretório

Exemplo:

shell> hg clone http://linuxtv.org/hg/v4l-dvb
shell> ls v4l-dvb

Commit:

Envia as alterações para o repositório local

Exemplo:

shell> vi arquivo.c (algumas alterações ocorreram neste momento)
shell> hg commit [arquivo]

Status:

Exibe o status dos arquivos do repositório local

Exemplo:

shell> hg status [arquivo]
M arquivo

Os códigos de status são:

M = Arquivo alterado (modified)
A = Adicionado
C = Sem alterações (clean) (Quando usa-se o parâmetro -c)
R = Arquivo removido
! = Arquivo removido mas continua no repositório
? = Arquivo não desconhecido
I = Arquivo ignorado
Sem retorno = Não houveram alterações no arquivo

Add:

Sinaliza os arquivos que serão adicionados ao repositório local

Exemplo::

shell> hg add arquivo
shell> hg commit (envia as alterações para o repositório local)

Remove:

Sinaliza os arquivos que serão removidos do repositório local

Exemplo:

shell> hg remove arquivo
shell> hg commit (envia as alterações para o repositório local)

Diff:

Exibe as alterações de um determinado arquivo

Exemplo:

shell> hg diff arquivo

Exemplo para visualizar alterações incluindo arquivos binários:
shell> hg diff -a

Opções:
-r = revisão

shell>hg diff -r revisão arquivo

ExtDiff:

A extensão extdiff permite especificar a ferramenta que sera utilizada para visualizar as alterações feitas em um determinado programa.

Por padrão, a extensão extdiff utiliza a ferramenta diff para comparar os arquivos e validar se houveram alterações.
Porém, é possível facilmente alterar a ferramenta de comparação de código, por exemplo de diff para kdiff3.

1) Adicione a extensão ao hgrc padrão ou ao .hgrc do local

Exemplo 1:

shell> vi /etc/mercurial/hgrc

Exemplo 2:

shell>vi ~/.hgrc

2) Adicione as linhas:

[extensions]
extdiff =

Neste momento será possível especificar a ferramenta para diffs. No exemplo abaixo iremos passar o programa kdiff3 como parâmetro:

Exemplo:

shell> hg extdiff -p /usr/bin/kdiff3

Opções:

-p = Ferramenta (program) por padrão é utilizado a ferramenta diff
-o = parâmetros (options) por padrão é passado ao extdiff as opções -Npru

Alias:

Ao invés de digitar hg extdiff -p /usr/bin/kdiff3 podemos criar um alias para digitar apenas:

shell> hg kdiff3

Adicione no seu arquivo ~/.hgrc local ou no hgrc geral /etc/mercurial/hgrc

[extensions]
extdiff =

[extdiff]
cmd.kdiff3 = kdiff3

# Caso queira passar opções, remova o comentário e adicione abaixo
# opts.kdiff3 =

Agora já é possível utilizar o novo comando

shell>hg kdiff3

Oops

Quem disse que o Linux não trava ?? Que atire a primeira pedra quem nunca viu ao menos um kernel panic na tela ? Pois bem, quando um erro grave ocorre no sistema, entre outras coisas que o kernel faz uma delas é exibir no terminal e/ou sistema de log, uma mensagem bastante conhecida por quem já passou por isso, a famosa mensagem de Oops. Trata-se de um dump do estado do CPU e da pillha do Kernel no momento em que o problema ocorreu. A mensagem de Oops mais conhecida é a que vem acompanhada de um kernel panic. Muitos ao se deparar com isso, percebem que nada funciona (na maioria dos casos), Ctrl+Alt+Backspace, teclas de função, e nem água, ai, simplesmente reiniciam a máquina, podendo causar ainda mais problemas.

Abaixo um exemplo de uma mensagem de Oops:

  1. Unable to handle kernel paging request at virtual address 00010015
  2. printing eip:
  3. c01e6608
  4. *pde = 00000000
  5. Oops: 0000
  6. CPU: 0
  7. EIP: 0010:[usb_unlink_urb+8/64] Tainted: P
  8. EFLAGS: 00010202
  9. eax: 00010001 ebx: d70c6494 ecx: c7c81000 edx: 00010001
  10. esi: c7c81640 edi: d70c6400 ebp: d70c64f0 esp: d2daded0
  11. ds: 0018 es: 0018 ss: 0018
  12. Process kpilotDaemon (pid: 30778, stackpage=d2dad000)
  13. Stack: d892a2ed 00010001 d70c6494 d70c6400 d3df51c0 00000000 d8924350 d70c6494
  14. d3df51c0 d725a000 cc5faa40 c16063c0 c018c460 d725a000 d3df51c0 d3df51c0
  15. cc5faa40 c16063c0 c8117e40 00000001 d3df51c0 bffff0e8 00000000 00000000
  16. Call Trace: [] [] [release_dev+576/1280]
  17. [n_tty_ioctl+257/1200] [tty_release+10/16]
  18. [fput+76/224] [filp_close+92/112] [sys_close+67/96] [system_call+51/56]
  19.  
  20. Code: 8b 42 14 85 c0 74 21 8b 80 bc 00 00 00 85 c0 74 17 8b 40 18

Esta mensagem pode ajudar aos desenvolvedores do kernel a depurar melhor o problema, e mesmo que você não reporte o bug, você pode se utilizar de um recurso que foi desenvolvido pensando nisto: As Magic SysRq Keys.

Trata-se de uma combinação de teclas que é utilizada para comunicar-se com o kernel do Linux, caso a opção CONFIG_MAGIC_SYSRQ tiver sido habilitada durante a compilação do kernel, ou em /proc/sys/kernel/sysrq.

Basta apertar Alt+PrintScreen+Tecla e a saída (dependendo da tecla) é enviada para o dmesg. Abaixo apenas algumas teclas:

t Lista de tarefas/processos com suas informações detalhadas
u Remonta todas as partições montadas, só que em read-only
m Mostra informações sobre o estado atual da memória
e Envia um sinal do tipo SIGTERM para todos os processos, exceto para o init

Existe a famosa combinação: Alt+PrintScreen+R E I S U B, onde basicamente mata todos os processos, sincroniza os discos, remonta todas os filesystems montados em read-only, e só então reinicia a máquina. Por tanto, antes de "meter o dedão" no botão de power, REISUB