ANÁLISE | Gerenciamento de hardware com Udev
Entenda o Udev
ANÁLISE
Hardware sob controle
O Udev executa e gerencia seu hardware no Linux. Explore o poderoso sistema e saiba
como customizar a configuração de seu hardware dentro das regras de udev.
por Klaus Knopper
N
os velhos tempos, drivers de
hardware faziam com que
os dispositivos se tornassem
operacionais e acessíveis aos usuários.
Embora eles ainda estejam presentes,
hoje em dia pensamos neles como
módulos – partes do kernel que podem tanto ser compilados em uma
parte estática do sistema, executados
durante a inicialização ou quando
um novo componente é adicionado.
O udev [1] é a ponte entre o suporte ao hardware crítico do kernel e o
espaço do usuário (userspace).
Neste artigo, exploro o sistema
udev e mostro como adicionar regras para customizar o processo de
configuração de hardware.
Dispositivos e
sistemas de arquivos
“Tudo é um arquivo”, no Linux. Essa
filosofia se aplica especialmente ao
acesso a hardware por meio de arquivos
de dispositivos, normalmente localizados dentro do diretório /dev ou em
seus subdiretórios. Os dois tipos principais de arquivos de dispositivos são
os block devices e os character devices.
Block devices (b) permitem acesso
arbitrário de leitura e escrita no espaço do endereço do hardware, organizados em unidades como “blocos”
(1024 bytes é o tamanho comum de
um bloco). Os exemplos mais comuns são discos rígidos e memórias.
Character devices (c) originalmente
oferecem acesso de leitura e escrita
caractere a caractere para o dispositivo, como os de dados em fita, entre
outros. Mas também são usados para
controlar recursos de hardware.
O kernel do Linux mantém controle sobre qual hardware pertence
a qual dispositivo, por número ao
invés de nome. Esses números são
os “major device ID” e “minor device
ID”, os quais podem ser descobertos
por meio do comando:
ls -l /dev/devicename
No exemplo da listagem 1, 8 é o “major device ID” do primeiro HD SATA
Listagem 1: IDs dos dispositivos
01
02
03
04
05
06
07
52
$ ls -l /dev/sd[ab] /dev/sd[ab][1-2]
brw-rw---- 1 root disk 8, 0 24. Apr 21:50 /dev/sda
brw-rw---- 1 root disk 8, 1 24. Apr 21:50 /dev/sda1
brw-rw---- 1 root disk 8, 2 24. Apr 21:50 /dev/sda2
brw-rw---- 1 root floppy 8, 16 24. Apr 21:50 /dev/sdb
brw-rw---- 1 root floppy 8, 17 24. Apr 21:50 /dev/sdb1
brw-rw---- 1 root floppy 8, 18 24. Apr 21:50 /dev/sdb2
(sda), que tem 0 (zero) como “minor
device ID” para todo o disco. Os números 1 e 2 são os identificadores “minor”
das duas primeiras partições do disco.
A próxima entrada de disco (o segundo disco SATA – sdb) começa com
o identificador “minor” 16. O grupo
floppy indica que o segundo disco é
um dispositivo de mídia removível, talvez um drive USB de memória flash.
Em vez de suportar acesso direto
de leitura e escrita para o hardware,
arquivos de dispositivos suportam
controles I/O (entrada e saída), que
são comandos que você pode enviar
para o driver do dispositivo enquanto
abre o arquivo do dispositivo por meio
de uma requisição do sistema ioctl().
Você pode usar controles de I/O para
operações como particionar e apagar
blocos, ou reconfigurar um dispositivo.
As chamadas read/write e ioctl já
foram os únicos meios de acessar hardware via dispositivos, mas a situação foi
Listagem 2: cpuinfo
01
02
03
04
05
06
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 28
model name : Intel(R)
Atom(TM) CPU Z520 @ 1.33GHz
07 stepping : 2
08 cpu MHz : 800.000
09 cache size : 512 KB
10 ...
www.linuxmagazine.com.br
Gerenciamento de hardware com Udev | ANÁLISE
aprimorada com a chegada de sistemas
de arquivos virtuais de configuração,
como o procfs e devfs. Sistemas de
arquivos virtuais como esses contêm
informações mais verbais e amigáveis
sobre as configurações do hardware.
O procfs, que é padrão em todos
os sistemas Linux modernos, permite que você veja informações de
processos, sistema e hardware em
tempo quase real, somente ao ler o
conteúdo dos arquivos residentes no
diretório /proc (listagem 2).
Ele também permite a configuração de opções diferentes, não necessariamente relacionadas ao hardware,
enquanto o sistema está em operação, como direcionamento de IP ou
gerenciamento de cache do drive.
# Enable IP-forwarding (routing)
$ echo 1 >
/proc/sys/net/ipv4/ip_forward
# Tell drive cache management
to only sync every 30 seconds
$ echo 3000 > /proc/sys/vm/
dirty_writeback_centisecs
O sistema de arquivos virtual ainda
mais novo, sysfs, suporta um nível
de interação com o hardware que vai
muito além de simples controles I/O.
Todos os dispositivos de hardware e
componentes da placa principal do
computador têm diretórios sysfs com
informações e arquivos de controle,
os quais permitem que se escrevam
scritps em Shell para controlar o
hardware. O udev é a ponte entre a
parte do kernel (como os módulos e
hardware que suportam os recursos do
mesmo) e o userpace (programas para
acessar e trabalhar com os hardwares).
Além disso, o udev tem alguns
plugins que permitem interação com
a sessão do desktop do usuário e programas de ajuda que exigem caixas
de diálogo e pop-ups sempre que o
status do hardware mudar.
Detecção de hardware
Detectar hardware é relativamente fácil
no Linux, porque todo dispositivo de
hardware tem um número de identifi-
Linux Magazine #82 | Setembro de 2011
cação de dispositivo PCI real ou virtual,
que abrange uma identificação do fornecedor e uma identificação do dispositivo.
O kernel Linux lê essas informações e
exibe-as nos subdiretórios /sys:
$ cat /sys/devices/pci0000:00/
0000:00:1c.1/0000:01:00.0/vendor
0x168c
$ cat /sys/devices/pci0000:00/
0000:00:1c.1/0000:01:00.0/device
0x002b
A parte ambiciosa é identificar um
driver que funcione com o dispositivo.
Se você sabe o ID (número identificador) do fornecedor e do dispositivo, pode
usar o comando lspci com o banco de
dados pci.ids para procurar por nomes
de dispositivos “legíveis para humanos”,
além do driver do dispositivo que deve
colocá-lo em estado operacional.
$ lspci -k -d 0x168c:0x002b
01:00.0 Network controller:
Atheros Communications Inc.
AR9285 Wireless Network Adapter
(PCI-Express) (rev 01)
Subsystem: AzureWave Device 1089
Kernel driver in use: ath9k
No Linux, o nome do dispositivo é
irrelevante. É importante selecionar o
módulo do kernel que lida com o dispositivo. Cada módulo tem uma tabela
embutida contendo os IDs de dispositivo conhecidos. O comando acima
identificou corretamente o driver do
kernel (ath9k) associado ao par composto pelo ID do fornecedor e pelo ID
do dispositivo (0x168c:0x002b), como o
comando modinfo mostra (listagem 3).
Um importante papel do udev, quando ele encontra um novo hardware,
é ler a assinatura do dispositivo (PCI
ID) e procurar por um módulo que
contenha o ID. O udev executa, então,
o módulo via modprobe, a menos que
ele esteja na blacklist (lista negra) em
/etc/modprobe.d/*.conf. O mecanismo
hotplug notifica que o udev tem um
novo dispositivo adicionado ao sistema,
mas sem um script especial para lidar
com os eventos (o diretório /proc/sys/
kernel/hotplug deve estar vazio).
Pré-requisitos
Apesar de não ser essencial, a maioria
das distribuições envolvem serviços
do sistema udev em scripts que substituem o /dev com um pequeno disco
de memória. O disco de memória cria
e remove nós de dispositivo rapidamente; essa técnica requer que um certo
arquivo seja criado (como o /dev/null,
/dev/zero, /dev/console) sem que sejam
Listagem 3: modinfo
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ modinfo ath9k
filename: /lib/modules/2.6.39-rc4/kernel/drivers/net/
wireless/ ath/ ath9k/ ath9k.ko
license: Dual BSD/GPL
description: Support for Atheros 802.11n wireless LAN cards.
author: Atheros Communications
alias: pci:v0000168Cd00000032sv*sd*bc*sc*i*
alias: pci:v0000168Cd00000030sv*sd*bc*sc*i*
alias: pci:v0000168Cd0000002Esv*sd*bc*sc*i*
alias: pci:v0000168Cd0000002Dsv*sd*bc*sc*i*
alias: pci:v0000168Cd0000002Csv*sd*bc*sc*i*
alias: pci:v0000168Cd0000002Bsv*sd*bc*sc*i*
alias: pci:v0000168Cd0000002Asv*sd*bc*sc*i*
alias: pci:v0000168Cd00000029sv*sd*bc*sc*i*
alias: pci:v0000168Cd00000027sv*sd*bc*sc*i*
alias: pci:v0000168Cd00000024sv*sd*bc*sc*i*
alias: pci:v0000168Cd00000023sv*sd*bc*sc*i*
depends: ath9k_hw,mac80211,ath9k_common,ath,cfg80211
vermagic: 2.6.39-rc4 SMP preempt mod_unload modversions ATOM
parm: debug:Debugging mask (uint)
parm: nohwcrypt:Disable hardware encryption (int)
parm: blink:Enable LED blink on activity (int)
parm: btcoex_enable:Enable wifi-BT coexistence (int)
53
ANÁLISE | Gerenciamento de hardware com Udev
Listagem 4: udevadm monitor
01
02
03
04
05
$ udevadm monitor --property --kernel --udev
o monitor retornará os eventos recebidos para:
DEV - o evento no qual udev envia após o processamento da regra
KERNEL - o uevent do kernel
UDEV [1303690744.003838] add /devices/pci0000:00/0000:00:1d.7/
usb1/1-2 (usb)
06 UDEV_LOG=3
07 ACTION=add
08 DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-2
09 SUBSYSTEM=usb
10 DEVNAME=/dev/bus/usb/001/003
11 DEVTYPE=usb_device
12 PRODUCT=1221/3234/0
13 TYPE=0/0/0
14 BUSNUM=001
15 DEVNUM=003
16 SEQNUM=2272
17 ID_VENDOR=USB2.0
18 ID_VENDOR_ENC=USB2.0
19 ID_VENDOR_ID=1221
20 ID_MODEL=Flash_Disk
21 ID_MODEL_ENC=Flash\x20Disk
22 ID_MODEL_ID=3234
23 ID_REVISION=0000
24 ID_SERIAL=USB2.0_Flash_Disk_1000000000000D8A
25 ID_SERIAL_SHORT=1000000000000D8A
26 ID_BUS=usb
27 ID_USB_INTERFACES=:080650:
28 MAJOR=189
29 MINOR=2
30 KERNEL[1303690745.279285] add /devices/pci0000:00/0000:00:1d.7/
usb1/1-2/1-2:1.0/host2/target2:0:0/2:0:0:0/block/sdb (block)
31 UDEV_LOG=3
32 ACTION=add
33 DEVPATH= /devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.0/
host2/target2:0:0/2:0:0:0/block/sdb
34 SUBSYSTEM=block
35 DEVNAME=sdb
36 DEVTYPE=disk
37 SEQNUM=2285
38 MAJOR=8
39 MINOR=16
40 KERNEL [1303690745.279497] add /devices/pci0000:00/0000:00:1d.7/
usb1/1-2/1-2:1.0/host2/target2:0:0/2:0:0:0/block/sdb/sdb1 (block)
41 UDEV_LOG=3
42 ACTION=add
43 DEVPATH= /devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.0/
host2/target2:0:0/2:0:0:0/block/sdb/sdb1
44 SUBSYSTEM=block
45 DEVNAME=sdb1
46 DEVTYPE=partition
47 SEQNUM=2286
48 MAJOR=8
49 MINOR=17
50 KERNEL [1303690745.281684] add /devices/pci0000:00/0000:00:1d.7/
usb1/1-2/1-2:1.0/host2/target2:0:0/2:0:0:0/scsi_generic/sg1
(scsi_generic)
51 UDEV_LOG=3
52 ACTION=add
53 DEVPATH= /devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.0/
host2/target2:0:0/2:0:0:0/scsi_generic/sg1
54 SUBSYSTEM=scsi_generic
55 DEVNAME=sg1
56 SEQNUM=2287
57 MAJOR=21
54
disparados por detecção de hardware.
Se o /dev/null ou dispositivos virtuais
de console ou terminal, principalmente, estão faltando, os scripts tendem
a criar diversos erros porque a saída
padrão e as mensagens de erros não
podem ser redirecionadas. Portanto, os
scripts de init do udev mantêm uma
cópia dos arquivos de dispositivos que
são copiados tão logo o disco de memória /dev é montado. O udev precisa
manter controle sobre seus próprios
arquivos de configuração e mudanças
no sistema de arquivos virtuais, o que
requer opções do kernel no tempo de
compilação para programar o inotify.
Para interagir com outros programas
do userspace relacionados a informações e acesso de hardware, o udev vem
com a biblioteca de sistema libudev.
Ação!
As três principais ações das quais
o udev é responsável são adicionar
hardware (add), remover hardware
(remove) e alterar ou notificar sobre
hardware existente (change). Para monitorar os resultados desses comandos,
use o comando udevadm monitor. As
opções --property, --kernel e --udev
produzem uma quantidade impressionante de informações cada vez
que algo acontece no seu conjunto
de hardware. Filtrei um exemplo para
mostrar as partes mais interessantes
sobre o que acontece quando um drive de memória flash USB é plugado.
O retorno do udevadm monitor (listagem 4) mostra o caminho de dispositivo do sistema a partir do sysfs,
números ID major e minor e nomes
de dispositivos sob os quais encontra-se
a primeira partição do drive USB, /
dev/sdb1. Alguns dos pares de valor
keyword = value mostrados na listagem 4 são variáveis de ambiente que
são exportadas para Shells de scripts
e programas chamados pelo udev.
Com a informação pronta, o udev
começa a conferir as regras (rules).
As regras oferecem uma camada
para que o usuário atribua nomes
www.linuxmagazine.com.br
Gerenciamento de hardware com Udev | ANÁLISE
representativos a cada dispositivo no
/dev, permitindo sua manipulação.
Elas são especificadas por
meio dos arquivos residentes em
/lib/udev/rules.d para os padrões
pré-definidos do sistema (as quais
você pode mudar, claro) e no
/etc/udev/rules.d para opções adicionais definidas pelo administrador. O
udev executa esses arquivos de regras
em ordem alfabética, mesclando os dois
caminhos citados. Nomes de arquivo
para regras geralmente começam com
um número de dois dígitos, e a maioria
termina com a extensão .rules.
Combinação*
As regras
Nos últimos dois anos, a sintaxe dos
arquivos .rules do udev passou por
várias modificações no que diz respeito a nomes de objetos e variáveis
de ambiente. Neste artigo, cubro a
versão 167 do udev.
Se os arquivos *.rules fossem simples como scripts Shell, dirigidos por
variáveis de ambientes, seria fácil
demais. Infelizmente, essa abordagem seria ineficiente porque muitos
eventos podem ser disparados cada
vez que algo muda, o que pode acontecer centenas de vezes por segundo.
Os arquivos de regras, portanto, têm
uma sintaxe rígida, específica do
udev. Essas regras são pré-compiladas
na inicialização do udev, em vez de
avaliadas em cada evento.
Em um arquivo de regras, uma linha
de código (que pode ser dividida em
várias com o uso da barra invertida (\),
tal como nos scripts Shell) lida com
uma regra. A regra é definida por dois
tipos de declarações: matches (tabela
1) e actions (tabela 2), separadas por
vírgulas, que são checadas e executadas desde que a declaração anterior
retorne o valor verdadeiro (true).
Contém
ACTION=="valor"
DRIVER=="valor"
KERNEL=="valor"
SUBSYSTEM=="valor"
SYSFS{keyword}=="valor"
ATTR{keyword}=="valor"
ATTRS{keyword}=="valor"
KERNELS, SUBSYSTEMS, DRIVERS
ENV{keyword}=="valor"
Valores “add” para dispositivos removíveis recentemente plugados;
“change” para dispositivos já ligados, mas ainda não reportados ou
reconfigurados; “remove” para dispositivos removidos ou desativados.
O driver (ou módulo de kernel) em uso para a condução do dispositivo.
O nome interno do kernel para o dispositivo (normalmente o mesmo
nome do dispositivo no diretório /dev). Wildcards Shell como ? (caracter
arbitrário) ou * (sequência arbitrária de caracteres) são suportados.
“block”, “pmcia”, “tty”, “usb” e outros, reportados no campo
SUBSYSTEM no monitor udevadm ou comando info.
Lê o nome do arquivo chave do diretório sysfs do dispositivo.
Caiu em desuso com as versões ATTR e ATTRS do udev.
Atributo de palavra-chave reportado pelo udev (normalmente lido do
/proc ou /sys) para o dispositivo atualmente detectado ou identificado.
Similar ao ATTR, mas para um “dispositivo pai” (parent device), que pode ser,
por exemplo, um disco, controlador ou sistema bus contendo partições.
O mesmo que KERNEL, SUSBSYSTEM e DRIVER relacionados ao dispositivo
detectado, mas criado para dispositivos pai (parent devices).
Uma variável de ambiente.
* Use != ao invés de == se você quiser verificar se o dispositivo é diferente.
Tabela 1: Combinações nas regras do udev.
Ação
ENV{keyword}="valor"
MODE="permissões"
GROUP="grupo"
Owner="nome_do_usuario"
SYMLIN="nome_arquivo"
SYMLIN+="nome_arquivo"
RUN="linha_comando"
RUN+="linha_comando"
ATTR{keyword}="valor"
Resultado
Configura e exporta uma variável de ambiente para o uso nas
próximas regras ou comandos. Variáveis de ambiente podem ser lidas
novamente em arquivos de rules udev por $env{keyworkd}.
Modo de permissão numérica para o arquivo de dispositivo criado em /dev.
Configura o grupo para o arquivo de dispositivo criado em /dev.
Configura o dono do arquivo de dispositivo criado em /dev.
Cria um único arquivo simbólico de ligação para o arquivo de dispositivo
adicional, associado com o dispositivo no diretório /dev.
Similar ao anterior, com a diferença de que adiciona um link a
mais, em vez de substituir todos os links por um.
Executa um comando Shell único.
Como o anterior, mas eventualmente adiciona outro comando após o
definido anteriormente, em vez de substituir todos os outros comandos.
Sobrescreve um atributo udev para as combinações subsequentes de rules udev.
Tabela 2: Ações nas regras do udev.
Linux Magazine #82 | Setembro de 2011
55
ANÁLISE | Gerenciamento de hardware com Udev
A sintaxe, de forma geral, em uma
linha de regras, é:
MATCH (match) == "texto",
MATCH=="texto", ... , ações
Listagem 5: udevadm info
01 $ udevadm info --query=all
--attribute-walk -name=/dev/sdb 1
02 looking at device ‘/devices/
pci0000:00/0000:00:1d.7/
usb1/1-1/1-1:1.0/host8/
target8:0:0/8:0:0 :0/block/
sdb/sdb1’:
03
KERNEL=="sdb1"
04
SUBSYSTEM=="block"
05
DRIVER==""
06
ATTR{partition}=="1"
07
ATTR{start}=="8064"
08
ATTR{size}=="15638656"
09
ATTR{ro}=="0"
10
[...]
11 [...]
12 looking at device ‘/devices/
pci0000:00/0000:00:1d.7/
usb1/1-1/1-1:1.0/host8/
target8:0:0/8:0:0:0/block/sdb’:
13
KERNEL=="sdb"
14
SUBSYSTEM=="block"
15
[...]
16
ATTRS{removable}=="1"
17
ATTRS{ro}=="0"
18
ATTRS{size}=="15646720"
19
ATTRS{events}==
"media_change"
20 looking at parent
device ‘/devices/
pci0000:00/0000:00:1d.7/
usb1/1-1/1-1:1.0/host8/
target8:0:0/8:0:0:0’:
21
KERNELS=="8:0:0:0"
22
SUBSYSTEMS=="scsi"
23
DRIVERS=="sd"
24
ATTRS{vendor}==" "
25
ATTRS{model}=="USB
DISK 2.0 "
26
ATTRS{rev}=="PMAP"
27
ATTRS{state}=="running"
28 [...]
29 looking at parent
device ‘/devices/
pci0000:00/0000:00:1d.7/
usb1/1-1’:
30
KERNELS=="1-1"
31
SUBSYSTEMS=="usb"
32
DRIVERS=="usb"
33
ATTRS{bMaxPower}=="200mA"
34
ATTRS{urbnum}=="412"
35
ATTRS{idVendor}=="13fe"
36
ATTRS{idProduct}=="3600"
37
ATTRS{bcdDevice}=="0100"
38
[...]
39
ATTRS{manufacturer}==" "
40
ATTRS{product}==
"USB DISK 2.0"
41
ATTRS{serial}==
"07A21A006E442637
56
Ao olhar para os vários arquivos de
regras na biblioteca /lib/udev/rules.d,
você pode se perguntar como descobrir todos os atributos dos dispositivos
(ATTR/ATTRS) necessários para criar uma
regra correspondente. O comando
udevadm dá acesso a informações sobre dispositivos específicos ligados ao
sistema, as quais você pode encontrar
usando o nome do dispositivo corrente
– nesse exemplo, a primeira partição
do segundo disco SATA/SCSI/USB
/dev/sdb1. O comando mostra o resultado da listagem 5; abreviei a listagem
para as partes mais relevantes da criação de regras udev.
Os atributos ATTR da listagem 5
estão diretamente associados com
o “block device” que consultei, enquanto os valores ATTRS são tirados dos
dispositivos do hardware de origem
– o disco SCSI e o subsistema de armazenamento USB. O udev confere
todas essas combinações ao avaliar um
arquivo de regra, de forma que você
possa usar combinações diferentes
para chegar à melhor combinação.
As ações do udev na tabela 2 podem ocorrer no momento em que o
hardware é identificado (outras ações
são possíveis, mas raramente usadas).
Para arquivos de regras, o udev suporta um esquema de substituição
para os valores de strings, como pode
ser visto na tabela 3.
Você encontrará um conjunto
completo de combinações, ações e
opções de configuração do udev no
Linux Archieve [2].
Escreva suas
próprias regras
Se quiser personalizar a forma com que
seu sistema trata um dispositivo de hardware, você pode escrever sua própria
regra de udev. O seguinte exemplo é
uma simples regra udev para memória flash USB examinada neste artigo.
Neste caso, eu quero montar a
memória flash no ponto /backup
quando ela é plugada:
# /etc/udev/rules.d/99
-mount-backup-disk.rules
ACTION=="add", SUBSYSTEM=="block",
ATTR{partition}=="1",
\ATTRS{serial}=="07A21A006E442637",
\RUN+="/bin/bash -c 'mkdir -p
/backup; mount -o umask=000
/dev/%k /backup'"
ACTION=="remove", SUBSYSTEM=="block",
ATTR{partition}=="1",
\ATTRS{serial}=="07A21A006E442637",
\RUN+="/bin/umount -l /backup'"
Essa regra confere se a primeira partição do dispositivo recentemente adicionado possui um número serial único
como 07A21A006E442637. Se encontrada,
a partição é montada como /backup.
O parâmetro umask para o mount libera as permissões de um sistema de
arquivos VFAT ou NTFS para leitura e
escrita, de forma que você não precisa
ser usuário root para criar arquivos no
/backup. Se você usa um sistema de
arquivos que suporta permissões de
arquivo, deve remover -o umask=000 e
programar as permissões do diretório
montado para um valor conveniente
para um usuário sem privilégios no
sistema. A regra de amostra para a
ação remove irá desmontar o diretório /backup, caso ele não tenha sido
desmontado pelo usuário, de forma
que o dispositivo possa ser realocado.
Você pode começar um backup
imediatamente com a ação add ao
estender o primeiro comando RUN
depois da montagem com algo como:
... && tar -zcPf /backup/
backup-'date +'%Y-%m-%d''
.tar.gz /home/work
e desmontando (umount) a partição
depois disso.
O próximo exemplo adicionará um
link simbólico chamado cdrom e outro
chamado dvd, se o dispositivo detectado
for identificado como um drive de CD
ou DVD, possivelmente substituindo
um link prévio para o arquivo de dispositivo, de forma que o link simbólico
sempre aponte para o dispositivo adicionado mais recentemente.
www.linuxmagazine.com.br
Gerenciamento de hardware com Udev | ANÁLISE
A linha END{ID_CDROM}==”?*” busca
uma variável de ambiente ID_CDROM
que não esteja vazia, o que significa que o dispositivo foi identificado
como drive de CD ou DVD.
# /etc/udev/rules.d/
99-cdrom-link.rules
SUBSYSTEM=="block",
ACTION=="change|add",
ENV{ID_CDROM}=="?*", \
SYMLINK+="cdrom", SYMLINK+="dvd"
O próximo exemplo inicia o daemon
do bluetooth quando um dispositivo
bluetooth é plugado, e interrompe o daemon quando o dispositivo é removido.
Adicionalmente, o modem serial do dispositivo bluetooth configurado como /dev/rfcomm3 em
/etc/bluetooth/rfcomm.conf é vinculado
a /dev/modem, de forma que programas
como o wvdial encontrem-no facilmente:
# /etc/udev/rules.d/99
-bluetooth-modem.rules
# Start/stop bluetooth daemon
on detection of bluetooth
host adapter
ACTION=="add|change",
\SUBSYSTEM=="bluetooth",
\KERNEL=="hci*",
\RUN+="/etc/init.d/bluetooth start"
ACTION=="remove",
\SUBSYSTEM=="bluetooth",
\KERNEL=="hci*",
\RUN+="/etc/init.d/bluetooth stop"
# Set modem link to bluetooth
serial device rfcomm3 only
ACTION=="add|change",
SUBSYSTEM=="tty",
\KERNEL=="rfcomm3",
SYMLINK+="modem"
O exemplo final adiciona uma
regra para criar logs de tempo e variáveis de ambiente exportadas para
o /tmp/udev-env.log, as quais podem
ser úteis no desenvolvimento de shell
scripts que usam essas variáveis.
# /etc/udev/rules.d/99
-log-env.rules
ACTION=="add|change|remove",
\RUN+="/bin/bash -c '(date; env;
echo) >>/tmp/udev-env.log'"
Após adicionar novos arquivos
de regras, ou alterar velhos arquivos, o udev deve notificar sobre as
Linux Magazine #82 | Setembro de 2011
mudanças [3]. Mesmo que a página
do manual diga que esse passo não
é necessário – porque o udev monitora os diretórios de configurações
regularmente – achei útil durante
meus experimentos, reiniciar o udev:
sudo /etc/init.d/udev reload
ou
Esse teste é somente para debug. Ele
não executa o programa e pode dar resultados incorretos porque alguns valores
podem ser diferentes ou não disponíveis
em uma simulação (listagem 6).
O teste revela quais scripts seriam
executados para esse dispositivo e
mostra quais variáveis estão programadas para a execução.
sudo udevadm control --reload-rules
Testes e debug
O comando udevadm test executa uma
simulação em seus arquivos de configuração com o caminho completo
do dispositivo como um parâmetro.
$ udevadm info --query=path
--name=/dev/sdb1 /devices/
pci0000:00/0000:00:1d.7/
usb1/1-1/1-1:1.0/host7/
target7:0:0/7:0:0:0/block/sdb/sdb1
Use o caminho para o udevadm test:
$ udevadm test --action=add
/devices/pci0000:00/0000:00:1d.7/
usb1/1-1/1-1:1.0/host7/
target7:0:0/7:0:0:0/block/sdb/sdb1
run_command: calling: test
udevadm_test: version 167
Interação com o
usuário do desktop
O udev inicia todas as suas ações
como usuário root por padrão, então você não deve se preocupar com
privilégios insuficientes ao lidar com
dispositivos. No entanto, o usuário
root não tem acesso ao desktop gráfico ao ser executado pelo usuário
sem privilégios, por duas boas razões:
➧ O servidor Xorg tem suas próprias permissões de sistema, habilitando ou desabilitando acesso à tela
com “cookies”, de forma a recusar
que outro usuário root inicie um
programa gráfico em uma sessão já
iniciada por outro usuário.
Listagem 6: udevadm test
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
parse_file: reading '/lib/udev/rules.d/40-hplip.rules' as rules file
(checagem de montes de outros arquivos de regras ...)
util_run_program: '/sbin/blkid -o udev -p /dev/sdb1' started
util_run_program: '/sbin/blkid' (stdout) 'ID_FS_TYPE=vfat'
util_run_program: '/sbin/blkid' (stdout)
'ID_FS_USAGE=filesystem'
util_run_program: '/sbin/blkid -o udev -p /dev/sdb1'
returned with exitcode 0
(outros programas de auxílio que investigam o dispositivo ...)
udevadm_test: ID_FS_VERSION=FAT32
udevadm_test: ID_FS_TYPE=vfat
udevadm_test: ID_FS_USAGE=filesystem
(outras saídas de debug do udev)
udevadm_test: run: '/usr/local/bin/askmount /dev/sdb1'
udev adm_test: run: '/bin/sh -c '/usr/sbin/rebuildfstab
-u knopper -i''
16 (mais programas definidos por RUN+=”programa” ...)
Substituição
Se expande para
%k
O nome de kernel do dispositivo (como
sda1 ou video0 sem o prefixo /dev).
$env{keyword}
A variável de ambiente keyword.
$attr{keyword}
Ao valor contido no atributo do udev ATTR{keyword}.
Tabela 3: Substituições de valores nas regras do udev.
57
ANÁLISE | Gerenciamento de hardware com Udev
➧ Em um ambiente multiusuário,
é aparentemente difícil saber qual usuário, usando qual display remoto,
é responsável pela inclusão de um
novo dispositivo.
A forma correta para um gerenciamento de hardware amigável no
desktop do usuário é por meio de
programas individuais que acessam
informações do udev via libudev,
parte da distribuição do udev. Programas que usam o libudev podem
ser facilmente conferidos para eventos relacionados a hardware, e então
notificados caso algo mude.
Para tornar as coisas mais complexas,
você tem o dbus, um “barramento de
sistema virtual” que recebe informações de udisks e upower (ambos usando
o libudev como clientes para o udev)
sempre que algo acontece relacionado
ao disco ou à gestão de energia. Programas de desktop, como o gerenciador de
arquivos, podem se comunicar com o
dbus para saber se qualquer dispositivo
de interesse aparece ou desaparece
sem se conectar ao udev diretamente.
Esse método é, atualmente, a forma
recomendada de acessar informações
de hardware do sistema udev. Do ponto
de vista do desenvolvedor, isso irá substituir completamente o HAL (camada
de abstração de hardware, em inglês).
Você ainda pode encontrar uma interface para o Hal ao examinar seu
/lib/udev/rules.d/90-hal.rules:
# pass all events to the HAL daemon
RUN+="socket:@/org/freedesktop/
hal/udev_event"
Se o HAL estiver em execução,
o udev enviará as informações de
todos os hardwares para o socket
associado e o HAL notificará todos
os programas compatíveis com ele.
Aparentemente, no Debian Testing,
o HAL sequer é um programa necessário, e você pode removê-lo com
segurança. Programas de desktop
ainda conseguirão processar informações relacionadas ao hardware
via dbus ou diretamente do libudev.
58
A filosofia “multiusuário” prevê que os usuários e o sistema não
devem interferir nos processos
de outro usuário. Se quiser escrever scripts para iniciar programas gráficos por meio do udev,
você pode “trapacear” ao conquis-
tar acesso ao display local para o
usuário root. O script na listagem 7
é um diálogo interativo que pede
permissão para montar a partição
de um pen drive USB recentemente plugado. O chamarei com
/usr/local/bin/askmount.
Listagem 7: askmount
01
02
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash
# /usr/local/bin/askmount
# (C) Klaus Knopper 2011
# License: GPL V2
# $DEVNAME (caminho absoluto), $ID_MODEL (product name)
# and $ID_FS_TYPE (sistema de arquivos) are environment variables
# exported by udev.
[ -n "$DEVNAME" ] || DEVNAME="$1"
if [ -z "$DEVNAME" ]; then
echo " $0 deve ser chamado com partição como argumento, saindo." >&2
exit 1
fi
# Conseguir acesso ao primeiro display que executar X
export DISPLAY=":0"
export XAUTHORITY=" $(ps f -C xinit -C Xorg -C X | sed -n
‘s/.*-auth \(.*\)/\1/p’ | head -1)"
# Checar se possui $XAUTHORITY antes de continuar.
if [ ! -r "$XAUTHORITY" ]; then
echo "Sem acesso ao display local, saindo." >&2
exit 1
fi
# Solicitando permissão do usuário para montar o dispositivo.
if zenity --question --title="Novo dispositivo encontrado"
--text="$ID_MODEL\n
33 Would you like to mount $DEVNAME?" ; then
34
35 # Ponto de montagem criado,
substituindo no /dev/ por /media/ no $DEVNAME
36 mountpoint="${DEVNAME/\/dev\///media/}"
37 mkdir -p "$mountpoint"
38
40 options="users"
41
42 # Se o sistema não suportar permissões,
43 # setar o padrão para leitura e escrita para todos.
44 case "$ID_FS_TYPE" in
45 *fat|msdos|ntfs) options="$options,umask=000" ;;
46 esac
47
48 # Feita a montagem, informar ao usuário sobre sucesso ou falha.
49 if mount -o "$options" "$DEVNAME" "$mountpoint"; then
50 zenity --info --timeout=5 --title="Dispositivo montado"
--text="Feito, agora você tem acesso ao dispositivo.
Não esqueça de desmontá-lo antes de desconectar."
53 else
54 zenity --info --timeout=5 --title="Error" --text="Desculpe,
não foi possível montar $DEVNAME."
55 fi
www.linuxmagazine.com.br
Gerenciamento de hardware com Udev | ANÁLISE
O script usa uma variável de ambiente que é programada pelo blkid,
ferramenta auxiliar do udev, ID_FS_TYPE
(contendo o tipo de sistema de arquivos da partição) e uma variável DEVNAME exportada pelo udev que contém
o caminho completo do dispositivo.
A listagem 7, que está disponível
para download no website da Linux
Magazine [4], usa o Zenity para oferecer caixas gráficas de diálogo. Você
pode ainda executar o script de forma
independente do udev e testá-lo, mas
ele só consegue montar um dispositivo
de forma bem sucedida quando executado como root. Nesse caso, as variáveis
de informação ID_MODEL e ID_FS_TYPE
não estarão disponíveis, a menos que
você as configure manualmente.
Agora, crie o arquivo de regras:
# /etc/udev/rules.d/99askmount.rules
ACTION=="add", SUBSYSTEM=="block",
\ENV{ID_FS_USAGE}=="filesystem",
\RUN+="/usr/local/bin/askmount
$env{DEVNAME}"
Se tudo funcionar (diga ao udev
para recarregar as regras), as caixas
de diálogos exibidas pelo Zenity, ao
Figura 1:O udev permite que você
acrescente caixas de diálogo
para personalizar o processo
de inicialização do hardware.
Linux Magazine #82 | Setembro de 2011
plugar na entrada USB uma memória
flash com partições que contenham
sistemas de arquivos, serão parecidas
com as caixas da figura 1.
Persistência
Um caso de uso interessante de
regras udev, as quais estão ativadas
por padrão na maioria das distribuições, é atribuir nomes persistentes para dispositivos específicos,
uma vez que eles foram detectados
pela primeira vez. Durante a detecção do dispositivo, as regras em
/lib/udev/rules.d/*generator.rules
criam e atualizam outro arquivo
de regras contendo um número
serial único de dispositivos como
interfaces de rede, drives de CD e
DVD e discos rígidos. Ao usar os
arquivos gerados, o udev "lembra",
por exemplo, como o disco foi nomeado, quando ele foi encontrado
pela primeira vez e sobrescreve o
nome do dispositivo de forma a
restaurar seu nome anterior. Pode
ser reconfortante saber que um
disco sempre será encontrado sob
o mesmo nome de dispositivo, sem
o impacto de outros hardwares. Por
outro lado, a numeração consecutiva de discos ou dispositivos de rede
pode levar a números muito elevados dependendo da quantidade de
dispositivos com a qual se está trabalhando. Se você perder ou quebrar um dispositivo, o nome nunca
mais será reutilizado, a menos que
você edite o arquivo persistente
( /etc/udev/rules.d/*persistent.
rules) manualmente.
Um dispositivo de rede persistente fica assim no /etc/udev/
rules.d/70-persistent-net.rules:
# USB device (rt73usb)
SUBSYSTEM=="net",
ACTION=="add", DRIVERS=="?*",
\ATTR{address}==
"00:23:cd:fd:4d:95",
\KERNEL=="wlan*", NAME="wlan1"
Se você ousar mudar o endereço
de hardware do dispositivo (usando
ifconfig debice hw ether new_mac),
o udev adicionará outra entrada
para ele.
Conclusão
Embora o udev ainda esteja em desenvolvimento, ele já emergiu como
uma ferramenta bem definida de
especificações de configuração, que
permite aos usuários obter informações sobre o hardware e criar scripts
para tarefas relacionadas a ele.
A interface libudev para programas
C/C++ torna possível a escrita de código que pode reagir diretamente a mudanças na configuração do hardware.
Com o udev, os usuários podem
manipular configurações – independentemente do desktop – por meio
do dbus a partir da sessão do usuário
gráfico, acessando várias ferramentas
administrativas para gerenciamento
de dispositivos que dependem do
udev e do dbus. ■
Mais informações
[1] Página do udev no kernel.
org: http://www.kernel.
org/pub/linux/utils/
kernel/hotplug/udev.html
[2] Lista completa das
combinações e ações do
udev: http://www.kernel.
org/pub/linux/utils/kernel/
hotplug/udev/udev.html
[3] Dicas e truques udev
no wiki do Archlinux:
https://wiki.archlinux.
org/index.php/udev
[4] Códigos para este artigo:
http://lnm.com.br/
issues/82/askmount.zip
Gostou do artigo?
igo?
Queremos ouvir sua opinião.
Fale conosco em
m
[email protected]
zine.com r
Este artigo no nosso
osso site:
s :
http://lnm.com.br/article/5661
r/artic 566
59