Controladores de Dispositivos em Linux
description
Transcript of Controladores de Dispositivos em Linux
![Page 2: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/2.jpg)
Sumário Módulos em Linux Escrevendo um controlador de dispositivo
tipo caractere Dispositivos de bloco e rede Arquitetura do hardware
Interrupções Portas de E/S DMA (Direct Memory Access) Barramentos ISA e PCI
![Page 3: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/3.jpg)
Arquitetura do Linux
![Page 4: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/4.jpg)
Módulos no Linux O Linux é um S.O. modular
Por exemplo, o suporte a determinado sistema de arquivos ou a certo dispositivo de hardware é fornecido através de módulos independentes
Em geral, tais módulos podem ser implantados dinamicamente, isto é, com o S.O. rodando, sem a necessidade de reinicialização
![Page 5: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/5.jpg)
Escrevendo um módulo simples
#define MODULE
#include <linux/module.h>
int init_module(void) {
printk("<1>Hello, world!\n"); return 0; }
void cleanup_module(void) {
printk("<1>Goodbye cruel world!\n"); }
![Page 6: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/6.jpg)
Por que printk e não printf ? Os módulos, quando implantados, tornam-
se parte do núcleo do S.O. Não é possível utilizar nenhuma biblioteca printk é implementada pelo S.O. Assemelha-se
à printf, mas não oferece suporte a números de ponto flutuante.
Os indicadores <n> fornecem a prioridade da mensagem. Quanto menor o número, maior é a prioridade Não funciona em consoles gráficos!
![Page 7: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/7.jpg)
Módulos x Programas Os módulos rodam no espaço de
endereçamento do núcleo do S.O. em modo supervisor. Isso exige alguns cuidados expeciais: Concorrência Segurança Controle de versão Tratamento de erros, alocação e desalocação
de recursos judiciosa O cuidado com ponteiros perdidos deve ser
redobrado. Pode-se travar completamente o sistema!
![Page 8: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/8.jpg)
Compilando, implantando e removendo o módulo
root# gcc -c -O2 hello.croot# insmod ./hello.oHello, world!root# rmmod helloGoodbye cruel world!root#
Diretiva de otimização Necessária algumas vezes, e não é
recomendado usar um valor maior Implantação e remoção dinâmicas
Pode-se testar várias vezes o módulo sem a necessidade de reinicialização
![Page 9: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/9.jpg)
A tabela de símbolos do Linux O comando ksyms lista essa tabela. É uma
associação de símbolos com endereços de memória.
insmod funciona como o programa de ligação de um compilador convencional. Permite que uma parte acesse funções ou
variáveis declarados na outra parte. Use static para os símbolos que não devem
ser exportados. É permitido que um módulo acesse os
símbolos exportados por outro módulo.
![Page 10: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/10.jpg)
O papel dos controladores de dispositivos
Fornecer uma camada de abstração do dispositivo
Prover um mecanismo de acesso
A política de acesso deve ser deixada sob responsabilidade do S.O.
![Page 11: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/11.jpg)
Tipos de dispositivos
Caractere Lembra uma cadeia de caractere
Bloco Basicamente são os dispositivos de armazenamento
de massa (discos)
Rede São aqueles que trocam dados com outras máquinas
![Page 12: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/12.jpg)
Dispositivos de caractere É o tipo de dispositivo mais simples que
existe. Está associado aqueles que oferecem uma cadeia de entrada ou saída de dados.
Implementam as operações de abertura, fechamento, leitura e escrita. Em alguns casos, também implementam outras funções, como a indexação (seek).
Assim como vários outros dispositivos em Linux, são acessíveis através de uma entrada no sistema de arquivos /dev.
![Page 13: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/13.jpg)
Números Maior e Menor Os arquivos especiais em /dev estão
associados a dois números que aparecem na listagem com ls -l
O número maior, isto é, o que aparece em primeiro, identifica qual módulo está associado a esse arquivo
O número menor é passado como parâmetro diretamente para o módulo. É útil quando temos diversos dispositivos sendo controlados pelo mesmo módulo.
![Page 14: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/14.jpg)
Criando um arquivo especial
Utiliza-se a opção c, seguida dos números maior e menor.
Os ajustes de permissão de acesso são feitos em seguida.
root# mknod /dev/teste c <N.Maior> <N.Menor> root# chmode 644 /dev/teste
![Page 15: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/15.jpg)
Um módulo mais sofisticado
Na inicialização do módulo, registra-se o mesmo como um driver de caractere, informando o número maior, um nome e uma estrutura file_operations. insmod registrará o módulo de acordo com
esse número maior o nome é o mesmo que aparece em
/proc/devices
int register_chrdev(unsigned int major, const
char *name, struct file_operations *fops);
![Page 16: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/16.jpg)
A estrutura file_operations As operações realizadas no arquivo
especial criado em /dev são encaminhadas pelo S.O. para o módulo correspondente. A estrutura file_operations é um “vetor”
contendo referências para as funções de operações de arquivos implementadas pelo módulo e que se tornaram acessíveis pelo S.O.
O número menor torna-se disponível para que o módulo possa interagir com o dispositivo correto.
![Page 17: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/17.jpg)
Resumindo: Um módulo possui um número maior Um arquivo especial possui um número maior insmod associa ao arquivo especial o módulo
correspondente. Fornece ao S.O. as ref. para as funções que implementam as operações de arquivo como abrir, fechar, ler ou escrever.
Ao acessar o arquivo especial, o S.O. chama a função correspondente à operação, fornecendo entre outros argumentos, o número menor.
![Page 18: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/18.jpg)
Dispositivos de bloco Basicamente são os dispositivos de
armazenamento de massa, (discos) São bem mais complicados que os
dispositivos de caractere. O número maior é distindo dos dispositivos
de caractere Pode coexistir um dispositivo de caractere e
outro de bloco no mesmo número maior.
![Page 19: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/19.jpg)
Registrando o dispositivo de bloco
#include <linux/fs.h>
int register_blkdev(unsigned int major, const char *name, struct block_device_operations *bdops);
int unregister_blkdev(unsigned int major, const char *name);
Principal diferença: block_device_operations x file_operations
![Page 20: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/20.jpg)
A estrutura block_device_operations
A função responsável pela escrita e leitura no dispositivo não permanece nessa estrutura por questões de eficiência.
Essa função porém é muito importante. É requisitada pelo S.O. somente quando as informações devem ser transferidas do ou para o disco.
Existem funções especiais correspondentes à montagem e desmontagem do dispositivo
![Page 21: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/21.jpg)
Dispositivos de rede Não possuem uma entrada em /dev. São
melhor representados como um canal de comunicação.
A maior diferença: Os dispositivos de bloco respondem à requisições provenientes apenas do S.O. local, enquanto que os dispositivos de rede respondem às requisições que chegam pelo canal de comunicação. O dispositivo passa a ser um elemento ativo.
![Page 22: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/22.jpg)
Dispositivos de rede Possuem funções relacionadas à tarefas
administrativas como configuração de parâmetros de comunicação e endereço.
O driver é responsável pela “camada física” de transmissão e não pelo protocolo. Sua interação com o S.O. ocorre em nível de pacotes completos.
Isso permite a independência entre os protocolos de hardware como Ethernet e token ring e protocolos de comunicação como IP ou IPX.
![Page 23: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/23.jpg)
Controle do tempo O Linux possui um relógio interno de 100Hz
jiffies, declarado em <linux/sched.h> Para uma precisão maior
do_gettimeofday() em <linux/time.h> Em <asm/msr.h> (machine-specific registers)
existem contadores com resolução próxima ao clock do sistema.
Em <linux/delay.h> existem 2 funções busy-waiting para temporizações da ordem de microsegundos e milisegundos.
![Page 24: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/24.jpg)
Arquitetura de hardware CPU Memória Portas de E/S Interrupções DMA - Direct Memory Access
Barramento ISA Barramento PCI
![Page 25: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/25.jpg)
Controle de interrupções As interrupções são necessárias quando
algum dispositivo precisa solicitar a atenção do S.O.
O registro e liberação da interrupção é feito por duas funções request_irq free_irq
![Page 26: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/26.jpg)
Registro e liberação do tratador de interrupções
<linux/sched.h>
int request_irq(unsigned int irq
void (*handler)(int, void *, struct pt_regs *)
unsigned long flags,
const char *dev_name,
void *dev_id);
void free_irq(unsigned int irq, void *dev_id);
![Page 27: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/27.jpg)
Tratadores de interrupções Devido ao número limitado de interrupções
do sistema, é aconselhável registrar um tratador de interrupções na operação de abertura do arquivo, ao invés de fazê-lo na instalação do módulo.
Devem ser rápidos e não podem entrar na fila de espera para execução, podendo causar impasses.
Compartilhamento de interrupções. A cada interrupção gerada, o S.O. invoca cada
um dos tratadores individualmente.
![Page 28: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/28.jpg)
Reservando portas de E/S
#include <linux/ioport.h>
int check_region(unsigned long start, unsigned long len);
struct resource *request_region( unsigned long start, unsigned long len, char *name);
void release_region(unsigned long start, unsigned long len);
![Page 29: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/29.jpg)
Acessando as portas de E/S
#include <asm/io.h>)
#Entrada/Saída de 8 bitsunsigned inb(unsigned port); void outb(unsigned char byte, unsigned port);
#Entrada/Saída de 16 bitsunsigned inw(unsigned port); void outw(unsigned short word, unsigned port);
#Entrada/Saída de 32 bitsunsigned inl(unsigned port); void outl(unsigned longword, unsigned port);
![Page 30: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/30.jpg)
Alguns cuidados com E/S Operações de E/S são muito mais lentas que
a velocidade dos processadores atuais. Se operações sucessivas acontecerem, corre-se
o risco de se perder dados. Existem funções que evitam o problema. São
elas: inb_p, outb_p, inw_p, etc. A escrita de dados em arquivos é controlada
pelo S.O. Para garantir que o dado foi enviado ao
hardware, use a função fflush().
![Page 31: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/31.jpg)
Memória do dispositivo: mmap Operação que mapeia uma região de
memória virtual no espaço do usuário para um dispositivo físico. Muito comum em interfaces gráficas
cat /proc/731/maps
08048000-08327000 r-xp 00000000 08:01 55505 /usr/X11R6/bin/XF86_SVGA
08327000-08369000 rw-p 002de000 08:01 55505 /usr/X11R6/bin/XF86_SVGA
40015000-40019000 rw-s fe2fc000 08:01 10778 /dev/mem
40131000-40141000 rw-s 000a0000 08:01 10778 /dev/mem
40141000-40941000 rw-s f4000000 08:01 10778 /dev/mem
![Page 32: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/32.jpg)
DMA - Direct Memory Access
Maneira eficiente de transferir dados para ou da memória RAM
O buffer de transferência deve ser alocado com cuidado, pois a região de memória será acessada pelo dispositivo. Em dispositivos ISA o problema é ainda maior. Em PCI, existe uma interface melhor, conhecida
como Bus Mastering Deve-se tomar o cuidado de mapear os
endereços virtuais para físicos.
![Page 33: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/33.jpg)
O barramento ISA
Obsoleto, mas ainda existem muitos dispositivos nesse padrão.
Portas de E/S limitadas a 1024 endereços Não permite endereçamento geográfico Memória de E/S limitada entre 640Kb e 1Mb,
e entre 15Mb e 16Mb Necessita de configuração manual
Tecnologia Plug and Play minimiza esse problema
![Page 34: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/34.jpg)
O barramento PCI Independente de plataforma Muito mais rápido que o ISA Possui endereçamento geográfico
Permite que os recursos, isto é, mapeamentos de memórias e linhas de interrupção sejam configurados na inicialização do sistema de forma automática.
A interface do Linux para dispositivos PCI facilita bastante o desenvolvimento de drivers para esses dispositivos.
![Page 35: Controladores de Dispositivos em Linux](https://reader035.fdocumentos.com/reader035/viewer/2022062221/568145b1550346895db2b247/html5/thumbnails/35.jpg)
Para saber mais
Rubini, A. & Corbet, J.; Linux Device Drivers, 2nd Edition, 2001 O´Reilly Livro disponível em formato eletrônico em
www.xml.com/ldd/chapter/book/
Código fonte do Linux