Valor retornado de Register_chdev do kernel Linux

Valor retornado de Register_chdev do kernel Linux

Esse vídeomostra um exemplo de módulo do kernel Raspberry Pi Linux que cria um novo dispositivo de caractere. Ele usa a API do kernel register_chdev. Em comentário ao vídeo (não consigo gerar link direto para ele), quanto ao valor de retorno de register_chdev, o autor afirma:

Se o valor de retorno não for igual a 0, o número do dispositivo já está em uso. Os 12 bits superiores do valor de retorno são o número do dispositivo principal, os 20 bits inferiores são o número do dispositivo secundário.

Eu acho que por "o número do dispositivo já está em uso" ele quer dizer "o número principal diferente de zero do dispositivo escolhido arbitrariamente no módulo do kernel já está em uso".

Apesar de várias páginas da web lidarem com isso (o oficial, entãoEsteeEste), não encontrei nenhuma informação sobre esta subdivisão interna do valor de retorno.

Se eu optar por criar (com meu módulo do kernel) um dispositivo com um número maior já em uso, o kernel nunca o aceitará e se recusará a registrar o dispositivo. Isso ocorre tanto quando o número maior que escolhi é igual ao de um dispositivo de bloco, quanto quando o número maior que escolhi é igual ao de um dispositivo de caractere. register_chdevsempre retorna um valor negativo. Neste último caso, em vez disso, eu esperava um valor de retorno positivo diferente de zero, com os 12 bits superiores representando o número principal do dispositivo e os 20 bits inferiores representando o número secundário do dispositivo (talvez maior que 0: se o número principal fosse já utilizado, talvez o sistema já possuísse pelo menos um dispositivo relacionado a ele, com o número menor 0).

É verdade o que afirma no comentário do Youtube? Onde posso encontrar alguma documentação sobre isso?


Estou executando o Raspbian 10, uname -amostra:

Linux raspberrypi 5.10.63-v7+ #1459 SMP Wed Oct 6 16:41:10 BST 2021 armv7l GNU/Linux

Responder1

register_chrdevem si não está documentado no kernel, massua definição é curta:

static inline int register_chrdev(unsigned int major, const char *name,
                  const struct file_operations *fops)
{
    return __register_chrdev(major, 0, 256, name, fops);
}

o que basicamente significa que ele chama__register_chrdevpara registrar um maior com uma gama completa de menores (256 menores começando em 0) e retornar o resultado dessa função. Este último está documentado como

Semajor== 0 esta função alocará dinamicamente um major e retornará seu número.

Semajor> 0 esta função tentará reservar um dispositivo com o número principal fornecido e retornará zero em caso de sucesso.

Retorna um -ve errno em caso de falha.

Não há previsão para devolução de menores, codificados ou não. O objetivo destas funções é registar um maior em qualquer caso, potencialmente com um subconjunto de menores; nem um único menor.

Ocodificaçãoentra em ação quando o driver do dispositivo lida com uma openchamada ou em qualquer outro momento em que ele precisa determinar a que menor (e talvez maior, se ele lidar com várias especialidades) um determinado dispositivo corresponde. Um driver recebe o inode que deve manipular; para um nó de dispositivo, que inclui o número do dispositivo, que codifica o maior e o menor. OMAJOReMINORmacros, ou a partir de um inode, oimajoreiminorfunções, devem ser usadas para extrair os valores.

Alguns dispositivos de caracteres oferecem multiplexação além dos principais mecanismos de registro descritos acima; verComo um driver variado controla todo esse hardware diferente?para um exemplo disso.

informação relacionada