Descrição
Vamos começar a discussão com o driver de personagem no Linux. O kernel categoriza os motoristas em três categorias:
Drivers de personagem - Estes são os drivers que não têm muitos dados para lidar. Poucos exemplos de motoristas de personagens são driver de tela de toque, driver UART, etc. Estes são todos os drivers de personagem, já que a transferência de dados é feita através do personagem por personagem.
Drivers de bloqueio - Estes são os drivers que lidam com muitos dados. A transferência de dados é feita em bloco por bloco, pois muitos dados precisam ser transferidos. Exemplo de drivers de bloco são SATA, NVME, etc.
Drivers de rede - Estes são os motoristas que funcionam no grupo de drivers de rede. Aqui, a transferência de dados é feita na forma de pacotes de dados. Motoristas sem fio como Atheros estão nessa categoria.
Nesta discussão, vamos nos concentrar apenas no driver de personagem.
Como exemplo, levaremos as operações simples de leitura/gravação para entender o driver de caracteres básico. Geralmente, qualquer driver de dispositivo tem essas duas operações mínimas. Operação adicional pode ser aberta, fechada, ioctl, etc. Em nosso exemplo, nosso motorista tem a memória no espaço do kernel. Essa memória é alocada pelo driver do dispositivo e pode ser considerada a memória do dispositivo, pois não há componente de hardware envolvido. O driver cria a interface do dispositivo no diretório /dev que pode ser usado pelos programas espaciais do usuário para acessar o driver e executar as operações suportadas pelo driver. Para o programa UsersPace, essas operações são como qualquer outra operações de arquivo. O programa espacial do usuário precisa abrir o arquivo do dispositivo para obter a instância do dispositivo. Se o usuário quiser executar a operação de leitura, a chamada do sistema de leitura pode ser usada para fazê -lo. Da mesma forma, se o usuário quiser executar a operação de gravação, a chamada do sistema de gravação poderá ser usada para obter a operação de gravação.
Driver de personagem
Vamos considerar implementar o driver de caracteres com as operações de dados de leitura/gravação.
Começamos com a instância dos dados do dispositivo. No nosso caso, é "struct cdrv_device_data".
Se vemos os campos dessa estrutura, temos CDEV, buffer de dispositivo, tamanho de buffer, instância de classe e objeto de dispositivo. Estes são os campos mínimos onde devemos implementar o driver de personagem. Depende do implementador do qual campos adicionais ele deseja adicionar para melhorar o funcionamento do driver. Aqui, tentamos alcançar o funcionamento mínimo.
Em seguida, devemos criar o objeto da estrutura de dados do dispositivo. Usamos a instrução para alocar a memória de maneira estática.
struct cdrv_device_data char_device [cdrv_max_minors];
Esta memória também pode ser alocada dinamicamente com "Kmalloc". Vamos manter a implementação o mais simples possível.
Devemos aceitar a implementação das funções de leitura e gravação. O protótipo dessas duas funções é definido pela estrutura do driver do dispositivo do Linux. A implementação dessas funções precisa ser definida pelo usuário. No nosso caso, consideramos o seguinte:
Leia: a operação para obter os dados da memória do driver para o espaço dos usuários.
static ssize_t cdrv_read (arquivo struct *, char __user *user_buffer, tamanho_t tamanho, loff_t *deslocamento);
Escreva: a operação para armazenar os dados para a memória do driver do espaço dos usuários.
static ssize_t cdrv_write (arquivo struct *, const char __user *user_buffer, tamanho_t tamanho, loff_t *deslocamento);
Ambas as operações, leia e escreva, precisam ser registradas como parte da STRIG FILE_OPERATATIONS CDRV_FOPS. Eles são registrados na estrutura do driver do dispositivo Linux no init_cdrv () do driver. Dentro da função init_cdrv (), todas as tarefas de configuração são executadas. Poucas tarefas são as seguintes:
O código de exemplo completo para o driver de dispositivo de caractere básico é o seguinte:
#incluirCriamos uma amostra makefile para compilar o driver de caracteres básico e o aplicativo de teste. Nosso código de motorista está presente no CRDV.C e o código do aplicativo de teste está presente em cdrv_app.c.
obj-m+= cdrv.oDepois que a emissão é feita para o Makefile, devemos obter os seguintes toras. Também temos o CDRV.KO e executável (cdrv_app) para nosso aplicativo de teste:
root@haxv-srathore-2:/home/cienauser/kernel_articles#Aqui está o código de amostra para o aplicativo de teste. Este código implementa o aplicativo de teste que abre o arquivo de dispositivo criado pelo driver CDRV e grava os "dados de teste". Em seguida, ele lê os dados do driver e o imprime depois de ler os dados a serem impressos como "dados de teste".
#incluirDepois de termos todas as coisas, podemos usar o seguinte comando para inserir o driver básico de caracteres no kernel Linux:
root@haxv-srathore-2:/home/cienauser/kernel_articles# insmod cdrv.KoDepois de inserir o módulo, recebemos as seguintes mensagens com DMESG e criamos o arquivo de dispositivo em /dev AS /dev /cdrv_dev:
root@haxv-srathore-2:/home/cienauser/kernel_articles# dmesgAgora, execute o aplicativo de teste com o seguinte comando no shell Linux. A mensagem final imprime os dados de leitura do driver, exatamente o mesmo que escrevemos na operação de gravação:
root@haxv-srathore-2:/home/cienauser/kernel_articles# ./cdrv_appTemos poucas impressões adicionais no caminho de gravação e leitura que podem ser vistas com a ajuda do comando dmesg. Quando emitimos o comando DMESG, obtemos a seguinte saída:
root@haxv-srathore-2:/home/cienauser/kernel_articles# dmesgConclusão
Passamos pelo driver de personagem básico que implementa as operações básicas de gravação e leitura. Também discutimos a amostra Makefile para compilar o módulo junto com o aplicativo de teste. O aplicativo de teste foi escrito e discutido para executar as operações de gravação e leitura do espaço do usuário. Também demonstramos a compilação e a execução do módulo e do aplicativo de teste com logs. O aplicativo de teste escreve poucos bytes de dados de teste e depois o lê de volta. O usuário pode comparar os dados para confirmar o funcionamento correto do driver e o aplicativo de teste.