LKMPG

De MediaWiki do Campus São José
Revisão de 11h46min de 19 de dezembro de 2019 por Msobral (discussão | contribs) (Criou página com 'Uma rápida compilação de materiais sobre o [http://www.kernel.org/ kernel Linux] e seus device drivers. = Tutoriais sobre programação de módulos do kernel = * [http://der...')
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para navegação Ir para pesquisar

Uma rápida compilação de materiais sobre o kernel Linux e seus device drivers.

Tutoriais sobre programação de módulos do kernel

Introdução

Para começarem a entender como desenvolver módulos e drivers para o kernel Linux, podem se basear neste livro:

Ele não é recente, e se baseia no kernel 2.6.x, mas muito do que ali está ainda é válido.

Vocês podem iniciar o estudo usando o próprio kernel do sistema operacional que está em seus laptops. Se for Ubuntu ou Debian, instalem o pacote linux-headers para poderem criarem seus módulos.

Etapa 1

Como primeiro módulo, experimentem criar um módulo que implemente um device driver para dispositivo orientado a caractere (ex: serial), que é o tipo mais simples de driver. Os livros inclusive usam como primeiro exemplo um driver desse tipo.

  • Arquivo:Lkm.zip: exemplo de módulo apresentado nas partes 1 e 2 do livro Linux Device Drivers.

Etapa 2

Nesse novo exercício, o dispositivo virtual guarda os dados nele escritos, e possibilita que sejam lidos por processos que o abram e façam chamadas read. Note o seguinte:

  1. A capacidade de armazenamento do dispositivo deve ser limitada .... se ele ficar cheio, uma nova tentativa de escrita deve falhar com algum código de erro (ex: EAGAIN).
  2. Quando um processo lê do dispositivo, a quantidade de bytes lidos deve ser retirada da memória.
  3. Cada novo read deve iniciar a partir da posição onde o read anterior terminou
  4. Se não houver dados para ler, read deve falhar com algum erro (ex: EAGAIN)

Note que, pela descrição acima, a memória do dispositivo deve funcionar como uma fila circular.

OBS: Códigos de erro estão em /usr/include/asm-generic/errno-base.h

Etapa 3

Quando concluir esse segundo exercício, modifique-o para que:

  1. Se uma escrita for realizada e a memória estiver cheia, então o processo que tentou a escrita deve ser bloqueado. Quando houver espaço na memória, o processo deve ser desbloqueado para terminar a operação de escrita.
  2. Mesma coisa quando se tentar ler e a memória do dispositivo estiver vazia


A cópia de valores entre buffers do driver e do processo que o acessa deve levar em conta que:

  • o buffer do driver está em espaço de kernel, que usa endereçamento real
  • o buffer do processo está em espaço de usuário, que usa endereçamento virtual

Por isso a cópia não pode ser feita diretamente com memcpy, strncpy, ou funções similares. A cópia precisa ser feita com funções da API do kernel, as quais traduzem os endereços virtuais do processo para reais (para isso elas usam a tabela de páginas do processo em questão). As funções são:


Existem outras, que podem ser vistas nestas documentações:

Dica: usar kfifo seria uma boa. No livro Linux Kernel Development tem uma seção que explica como funciona kfifo, e como se pode usá-la - ver Queues no capítulo 6.

A próxima capacidade do driver que pedi é que seja capaz de bloquear um processo que tente ler o dispositivo, mas não existam dados para ler. E o mesmo deve ocorrer se um processo tentar escrever no dispositivo, mas ele estiver cheio. Lembrem que a ideia é que o dispositivo represente um named pipe, o que implica haver uma fila.

Este tutorial explica de forma bastante clara como fazer com que processos esperem por alguma condição dentro de um driver:

https://sysplay.in/blog/linux-kernel-internals/2015/10/waiting-blocking-in-linux-driver/

Caros, o próximo passo envolve entender a temporização de tarefas dentro do kernel. O kernel fornece facilidades para medição de tmpo decorrido (jiffies), espera ocupada ou bloqueada (timeout), execução de uma ação em momento específico (timer), e execução de ação em momento oportuno (tasklet e workqueue). Cada mecanismo tem sua aplicação e suas limitações, como se pode ler no capítulo 7 do livro Linux Device Drivers:

https://www.oreilly.com/library/view/linux-device-drivers/0596005903/ch07.html


A próxima tarefa envolve modificar o seu device driver para que as informações gravadas na fila tenham um certo tempo de vida ... Cada conjunto de bytes gravados na fila deve lá permanecer por, no máximo, algum tempo predefinido (ex: 5 segundos). Se esse tempo passar e aqueles bytes ainda estiverem na fila, eles devem ser retirados e descartados. Notem que o controle de tempo decorrido deve ser feito com base no instante em que os dados entraram na fila: se um processo gravar 4 bytes no dispositivo no instante 0, depois 7 bytes no instante 2, e finalmente 3 bytes no instante 4, os primeiros 4 bytes devem ser descartados no instante 5, os 7 bytes no instante 7, e os 2 bytes finais no instante 9 (caso não tenham sido lidos do dispositivo).