1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE slides SYSTEM "/usr/share/xml/docbook/custom/slides/3.3.1/schema/dtd/slides-full.dtd">
7 <title>Linux Device Drivers</title>
8 <author><firstname>Thadeu</firstname><surname>Cascardo</surname></author>
12 <title>Introdução</title>
14 Dispositivos em sistemas POSIX são arquivos no diretório /dev. Como quaisquer
15 outros arquivos no POSIX, eles podem ser abertos, fechados, lidos, escritos,
16 posicionados, controlados, entre outros.
20 Exemplos de arquivos de dispositivos:
26 /dev/sda - Um dispositivo de bloco SCSI
31 /dev/ttyS0 - Um dispositivo terminal serial
39 <title>Chamandas de Entrada e Saída em POSIX</title>
41 Sistemas POSIX possuem algumas chamadas padrões para E/S. Já que dispositivos
42 são arquivos, essas mesmas chamadas são utilizadas para trabalhar com
43 dispositivos. Vamos trabalhar com as seguintes chamadas:
70 A chamada de systema open abre um arquivo. Quando estivermos trabalhando com
71 dispositivo, é quando alguma inicialização deve ser feita. Alguns dispositivos
72 só podem ser abertos por um processo de cada vez.
75 int open (char * filename, int flags);
78 flags podem ser O\_RDONLY, O\_WRONLY, O\_RDWR e muitas outras, algumas menos
79 importantes para dispositivos.
85 fd = open ("/dev/ttyS0", O\_RDWR);
92 A chamada de sistema close fecha um arquivo aberto.
108 A chamada de sistema read lê de um arquivo aberto para um buffer. Para
109 dispositivos, ela lê de um dispositivo.
112 int read (int fd, char *buffer, int bsz);
115 read retorna o número de bytes escritos no buffer, que pode ser menor que o
116 número de bytes requisitados por diferentes razões.
122 c = read (fd, buffer, sizeof (buffer));
129 A chamada de sistema write escreve dados de um buffer em um arquivo aberto. Para
130 dispositivos, ela escreve no dispositivo.
133 int write (int fd, char *buffer, int bsz);
136 write retorna o número de bytes escritos no arquivo, que pode ser menor que o
137 número de bytes requisitados por diferentes razões.
143 c = write (fd, buffer, strlen (buffer));
150 A chamada de sistema lseek muda a posição corrente do arquivo, permitindo a
151 leitura ou escrita naquela posição. Posicionar em um dispositivo pode ter
152 diferentes significados.
155 off\_t lseek (int fd, off\_t pos, int whence);
158 O significado da posição depende do valor de whence, que pode ser
159 SEEK\_SET (a posição absoluta), SEEK\_CUR (relativa a posição corrente),
160 SEEK\_END (relativa ao fim do arquivo).
166 lseek (fd, 0, SEEK\_END);
173 A chamada de sistema ioctl é uma operação "pega-tudo". Para aquelas operações
174 que não se encaixam no modelo leitura/escrita, ioctl permite ao usuário enviar
175 um comando com um argumento opcional ao dispositivo. Esse comando pode aceitar
176 entrada ou gerar saída.
179 int ioctl (int fd, int request, char *arg);
182 O último argumento é opcional e depende do tipo de requisição. Todo dispositivo
183 ou classe de dispositivo pode ter seu diferente conjunto de ioctl's.
189 struct ifreq req; ioctl (fd, SIOCGIFFLAGS, \&req);
194 <title>Módulos do Linux</title>
196 Linux é modularizado. Drivers, sistemas de arquivos, protocolos de rede e outros
197 podem ser carregados em tempo de execução. Todo módulos tem uma função init e
201 Módulos podem ter parâmetros. Em tempo de carga, parâmetros, que podem ser
202 booleanos, inteiros ou strings, são dados pelo usuário.
207 <title>Tipos e números de dispositivos</title>
209 Dispositivos no Linux podem ter diferentes tipos, incluindo dispositivos de
210 caractere, dispositivos de bloco e dispositivos de rede. Tanto dispositivos de
211 caractere quanto de bloco têm números identificadores, um número maior e um
217 <title>Alocação de dispositivos de caractere</title>
219 No Linux, números maior e menor devem ser requisitados ou alocados. As chamadas
220 para fazê-lo para os dispositivos de caractere são:
223 int register\_chrdev\_region (dev\_t first, unsigned int count, char
225 int alloc\_chrdev\_region (dev\_t *dev, unsigned int firstminor,
226 unsigned int count, char *name);
227 void unregister\_chrdev\_region (dev\_t dev, unsigned int count);