No Capítulo 8, nós instalamos o processo de segundo plano Udev quando systemd foi construído. Antes de entrarmos nos detalhes referentes a como o Udev funciona, um histórico breve dos métodos anteriores de manuseio de dispositivos é oportuno.
Sistemas Linux em geral tradicionalmente usavam um método estático de
criação de dispositivo, pelo qual um grande número de nós de
dispositivo era criado sob /dev
(às
vezes literalmente milhares de nós), independente de se os
dispositivos de hardware correspondentes atualmente existissem. Isso
tipicamente era feito via um script MAKEDEV, o qual continha um número
de chamadas ao aplicativo mknod com os números relevantes de
dispositivo maior e menor para cada dispositivo possível que pudesse
existir no mundo.
Usando o método Udev, nós de dispositivo somente são criados para
aqueles dispositivos que são detectados pelo núcleo. Esses nós de
dispositivo são criados a cada vez que o sistema inicializa; eles
serão armazenados em um sistema de arquivos devtmpfs
(um sistema de arquivos virtuais que
reside inteiramente na memória do sistema). Nós de dispositivo não
exigem muito espaço, de forma que a memória que é usada é
insignificante.
Em fevereiro de 2000, um novo sistema de arquivos chamado
devfs
foi mesclado no núcleo 2.3.46
e foi tornado disponível durante as séries 2.4 de núcleos estáveis.
Embora ele estivesse presente no próprio fonte do núcleo, esse
método de criar dispositivos dinamicamente nunca recebeu suporte
decisivo dos(as) desenvolvedores(as) centrais do núcleo.
O problema principal com a abordagem adotada pelo devfs
era a maneira como ele lidava com
detecção, criação e nomenclatura de dispositivo. O último problema,
esse da nomenclatura de nó de dispositivo, era talvez o mais
crítico. Geralmente é aceito que, se nomes de dispositivo forem
configuráveis, [então] a política de nomenclatura de dispositivo
deveria ser escolhida pelos(as) administradores(as) do sistema e
não imposta a eles(as) pelos(as) desenvolvedores(as). O sistema de
arquivos devfs
também sofria com
algumas condições que eram inerentes ao projeto dele; essas não
poderiam ser corrigidas sem uma revisão substancial do núcleo. O
devfs
ficou marcado como obsoleto
por um longo tempo, e finalmente foi removido do núcleo em junho de
2006.
Com o desenvolvimento da árvore do núcleo instável 2.5, liberada
posteriormente como a série 2.6 dos núcleos estáveis, um novo
sistema de arquivos virtuais chamado sysfs
veio a existir. O trabalho do
sysfs
é o de fornecer informação a
respeito da configuração de hardware do sistema para processos do
espaço de usuário(a). Com essa representação visível ao espaço de
usuário(a), tornou-se possível desenvolver um substituto de espaço
de usuário(a) para o devfs
.
O sistema de arquivos sysfs
foi
brevemente mencionado acima. Alguém possivelmente questione como
o sysfs
sabe a respeito dos
dispositivos presentes em um sistema e quais números de
dispositivo deveriam ser usados para eles. Controladores que
tenham sido compilados internamente no núcleo registram os
objetos deles em sysfs
(devtmpfs
internamente) assim que são detectados pelo núcleo. Para
controladores compilados como módulos, o registro acontece quando
o módulo for carregado. Assim que o sistema de arquivos
sysfs
for montado (em
/sys
), os dados os quais os
controladores tenham registrado com sysfs
ficam disponíveis para os processos de
espaço de usuário(a) e para o udevd para processamento (incluindo
modificações para nós de dispositivo).
Arquivos de dispositivo são criados pelo núcleo no sistema de
arquivos devtmpfs
. Qualquer
controlador que deseje registrar um nó de dispositivo usará o
devtmpfs
(via núcleo do
controlador) para fazê-lo. Quando uma instância do devtmpfs
é montada em /dev
, o nó de dispositivo inicialmente será
exposto para o espaço de usuário(a) com um nome, permissões e
proprietário(a) fixos.
Pouco tempo depois, o núcleo enviará um uevent para udevd. Baseado nas regras
especificadas nos arquivos dentro dos diretórios /etc/udev/rules.d
, /usr/lib/udev/rules.d
e /run/udev/rules.d
, udevd criará links simbólicos
adicionais para o nó de dispositivo ou mudará as permissões,
proprietário(a) ou grupo deles, ou modificará a entrada interna
(nome) de base de dados do udevd para aquele objeto.
As regras nesses três diretórios são numeradas e todos os três
diretórios são mesclados. Se udevd não puder encontrar uma
regra para o dispositivo que ele esteja criando, [então] ele
deixará as permissões e propriedade no que devtmpfs
usou inicialmente.
Controladores de dispositivo compilados como módulos
possivelmente tenham apelidos construídos dentro deles. Apelidos
são visíveis na saída gerada do aplicativo modinfo e geralmente estão
relacionados aos identificadores específicos ao barramento dos
dispositivos suportados por um módulo. Por exemplo, o controlador
snd-fm801 suporta
dispositivos PCI com ID de fornecedor 0x1319 e ID de dispositivo
0x0801 e tem um apelido de “pci:v00001319d00000801sv*sd*bc04sc01i*”.
Para a maioria dos dispositivos, o controlador de barramento
exporta o apelido do controlador que lidaria com o dispositivo
via sysfs
. Por exemplo, o arquivo
/sys/bus/pci/devices/0000:00:0d.0/modalias
pode
conter a sequência de caracteres “pci:v00001319d00000801sv00001319sd00001319bc04sc01i00”.
As regras padrão fornecidas com o Udev causarão udevd chamar /sbin/modprobe com o conteúdo
da variável de ambiente do uevent MODALIAS
(o qual deveria ser o mesmo que o
conteúdo do arquivo modalias
em
sysfs), dessa forma carregando todos os módulos cujos apelidos
correspondem a essa sequência de caracteres depois da expansão de
carácter curinga.
Nesse exemplo, isso significa que, em adição a snd-fm801, o obsoleto (e indesejado) controlador forte será carregado se ele estiver disponível. Veja-se abaixo para maneiras nas quais o carregamento de controladores indesejados pode ser evitado.
O próprio núcleo também é capaz de carregar módulos para protocolos de rede de comunicação, sistemas de arquivos e suporte NLS sob demanda.
Quando você pluga um dispositivo, como um reprodutor de MP3 Universal Serial Bus (USB), o núcleo reconhece que o dispositivo agora está conectado e gera um uevent. Esse uevent é então tratado pelo udevd como descrito acima.
Existem uns poucos possíveis problemas quando se trata de criar automaticamente nós de dispositivos.
O Udev só carregará um módulo se ele tiver um apelido específico
de barramento e o controlador de barramento exportar
adequadamente os apelidos necessários para sysfs
. Em outros casos, deve-se organizar o
carregamento de módulo por outros meios. Com o Linux-6.4.12, o
Udev é conhecido por carregar controladores escritos
adequadamente para dispositivos INPUT, IDE, PCI, USB, SCSI, SERIO
e FireWire.
Para determinar se o controlador de dispositivo que você exige
tem o suporte necessário para o Udev, execute modinfo com o nome do módulo
como o argumento. Agora tente localizar o diretório do
dispositivo sob /sys/bus
e
verifique se existe um arquivo modalias
lá.
Se o arquivo modalias
existir em
sysfs
, [então] o controlador
suporta o dispositivo e pode falar com ele diretamente, mas não
tem o apelido, isso é um defeito no controlador. Carregue o
controlador sem a ajuda do Udev e espere que o problema seja
corrigido posteriormente.
Se não existir arquivo modalias
no
diretório relevante sob /sys/bus
,
[então] isso significa que os(as) desenvolvedores(as) do núcleo
ainda não adicionaram suporte modalias para esse tipo de
barramento. Com o Linux-6.4.12, esse é o caso com barramentos
ISA. Espere que esse problema seja corrigido em versões
posteriores do núcleo.
O Udev não é destinado para carregar controladores “encapsuladores”, tais como snd-pcm-oss, e controladores de não hardware, tais como loop, de maneira alguma.
Se o módulo “encapsulador” somente aprimora a
funcionalidade fornecida por algum outro módulo (por exemplo,
snd-pcm-oss aprimora a
funcionalidade de snd-pcm
tornando as placas de som disponíveis para aplicações OSS),
[então] configure o modprobe para carregar o
encapsulador depois que o Udev carregar o módulo encapsulado.
Para fazer isso, adicione uma linha “softdep” ao arquivo
/etc/modprobe.d/
correspondente. Por exemplo:
<nome_arquivo>
.conf
softdep snd-pcm post: snd-pcm-oss
Observe que o comando “softdep” também permite dependências
pre:
, ou uma mistura de ambas as
dependências pre:
e post:
. Veja-se a página de manual modprobe.d(5)
para mais informação a respeito
da sintaxe e recursos “softdep”.
Ou não construa o módulo, ou coloque-o na lista negra em um
arquivo /etc/modprobe.d/blacklist.conf
como feito com o
módulo forte no exemplo
abaixo:
blacklist forte
Módulos em listas negras ainda podem ser carregados manualmente com o comando explícito modprobe.
Isso geralmente acontece se uma regra inesperadamente corresponder com um dispositivo. Por exemplo, uma regra mal escrita pode corresponder com ambos um disco SCSI (como desejado) e o dispositivo genérico SCSI correspondente (incorretamente) por fornecedor(a). Encontre a regra infratora e torne-a mais específica, com a ajuda do comando udevadm info.
Isso possivelmente seja outra manifestação do problema anterior.
Se não, e sua regra usar atributos do sysfs
, [então] isso possivelmente seja um
problema de temporização do núcleo, a ser corrigido em núcleos
posteriores. Por hora, você pode contorná-lo criando uma regra
que aguarda o atributo usado do sysfs
e o adiciona ao arquivo /etc/udev/rules.d/10-wait_for_sysfs.rules
(crie
esse arquivo se ele não existir). Por favor, notifique a lista
LFS Development se você o fizer e isso ajudar.
Primeiro, esteja certo(a) de que o driver está construído internamente no núcleo ou já carregado como um módulo e que o Udev não está criando um dispositivo mal nomeado.
Se um controlador do núcleo não exportar os dados dele para o
sysfs
, [então] o Udev carece da
informação necessária para criar um nó de dispositivo. Isso é
mais provável de acontecer com controladores terceirizados
oriundos de fora da árvore do núcleo. Crie um nó de dispositivo
estático em /usr/lib/udev/devices
com os números maior/menor apropriados (veja-se o arquivo
devices.txt
dentro da documentação
do núcleo ou a documentação fornecida pelo(a) fornecedor(a) do
controlador terceirizado). O nó de dispositivo estático será
copiado para /dev
pelo udev.
Isso é devido ao fato de o Udev, pelo projeto, lidar com uevents e carregar módulos em paralelo e, assim, em uma ordem imprevisível. Isso nunca será “corrigido”. Você não deveria confiar nos nomes de dispositivos do núcleo sendo estáveis. Em vez disso, crie suas próprias regras que fazem links simbólicos com nomes estáveis baseados em alguns atributos estáveis do dispositivo, tais como um número de série ou a saída gerada dos vários utilitários *_id instalados pelo Udev. Veja-se a Seção 9.4, “Gerenciando Dispositivos” e Seção 9.2, “Configuração Geral da Rede de Comunicação” para exemplos.
Documentação útil adicional está disponível nos seguintes sítios:
Uma implementação de espaço de usuário(a) do devfs
http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf
O Sistema de Arquivos sysfs
http://www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf