9.3. Visão Geral do Manuseio de Dispositivo e de Módulo

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.

9.3.1. Histórico

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.

9.3.2. Implementação do Udev

9.3.2.1. Sysfs

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).

9.3.2.2. Criação de Nó 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.

9.3.2.3. Carregamento de Módulo

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 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 correspondam 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.

9.3.2.4. Lidando com Dispositivos Plugáveis a Quente/Dinâmicos

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.

9.3.3. Problemas ao Carregar Módulos e Criar Dispositivos

Existem uns poucos possíveis problemas quando se trata de criar automaticamente nós de dispositivos.

9.3.3.1. Um Módulo do Núcleo Não é Carregado Automaticamente

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.10.5, 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.10.5, 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.

9.3.3.2. Um Módulo do Núcleo Não é Carregado Automaticamente e o Udev Não é Destinado para Carregá-lo

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/<nome_arquivo>.conf correspondente. Por exemplo:

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 do softdep.

9.3.3.3. O Udev Carrega Algum Módulo Indesejado

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.

9.3.3.4. O Udev Cria um Dispositivo Incorretamente ou Faz o Link Simbólico Errado

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.

9.3.3.5. Regra do Udev Funciona de Forma Não Confiável

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.

9.3.3.6. O Udev Não Cria um Dispositivo

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.

9.3.3.7. A Ordem de Nomenclatura do Dispositivo Muda Aleatoriamente Depois de Reinicializar

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 as tuas 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.

9.3.4. Leitura Útil

Documentação útil adicional está disponível nos seguintes sítios: