cópia de: https: //blog.csdn.net/weixin_42462202/article/details/99887783
entrada de driver Linux (a) dispositivo de caracteres base motorista do
artigo diretórios
entrada de driver Linux (a) caracteres dispositivo de base motorista
uma Introdução unidade
II conceito de driver de dispositivo de caracteres
terceiro lugar, o dispositivo de caracteres registrada
quatro ou compilar o módulo
cinco módulos de carga
sexto lugar, criar um nó de dispositivo
sete teste de
uma unidade Introdução
driver Linux para driver de dispositivo de caracteres, um drivers de dispositivo bloco, driver de dispositivo de rede
driver de dispositivo de caracteres
Um personagem dispositivos obrigação, a fim de série de acesso, como levou, um ecrã táctil, um mouse, etc.
Chamada acessível através de abrir, fechar, ler, escrever e outros sistemas
driver de dispositivo bloco
dispositivo de acesso bloco pode estar em qualquer ordem, em unidades de blocos para operar, como um disco rígido, e assim o EMMC
Há grandes diferenças conduzem os dispositivos de bloco projeto e caráter, mas também pode ser acessado via abrir, fechar, ler, escrever e outras chamadas de sistema, mas estes são geralmente usando o sistema de arquivos para gerenciar
driver de dispositivo de rede
dispositivo de rede é projetada para receber e enviar pacotes de dados, no sistema de arquivos, e não há nenhum nó de dispositivo correspondente, acessado através de interface de socket
Este trabalho, principalmente no dispositivo de caracteres
Em segundo lugar, o conceito de drivers de dispositivo de caracteres
no Linux tudo é um arquivo, como um desempenho do dispositivo conduzido no sistema de arquivos como / dev /, camada de aplicação levou nó de dispositivo através de abrir, ler, escrever e outras chamadas de sistema pode ser controlado levou
Por exemplo, quero levou luz, abrir a gravação de arquivos do dispositivo 1
int fd;
int val = 1;
Open = FD ( "/ dev / led", XXX);
Write (FD, e Val, o sizeof (Val));
de tal forma que ele pode ser conduzido iluminado
Agora pense sobre a questão, porque assim que você pode fazer o up luz led?
Para obter luzes LED, você deve operar o hardware, hardware operacional que faz parte da unidade de trabalho levou concluída
A maneira mais fácil é, para a camada de aplicação levou à operação de abertura, em seguida, a um correspondente condutor de levou led_open. Levou à camada de aplicação para as operações de escrita, a operação levou a um correspondente um dos led_write condutor, em seguida, a operação led_write para controlar o hardware, então o controlo levou
Em seguida, no dispositivo levou os nós aberta, chamada de sistema de gravação, como chamar a led_open do motorista, led_write isso?
Quando a camada de aplicativo chama aberta, ler, escrever e outras operações, fará com que uma exceção, fazendo com que o sistema se torne modo kernel, e, em seguida, para executar a chamada de sistema correspondente sys_open, sys_read, sys_write etc.
Irá encontrar o driver apropriado sys_open, sys_read, sys_write, e em seguida, chama ler, hardware aberto, gravação do motorista para operar
Como mostrado na FIG.
Sys_open em seguida, chamar um sistema de arquivos virtual, como você encontrou motorista levou em vez dos outros motoristas fazer?
Primeiro, conte-nos sobre o número do dispositivo
Cada dispositivo possui um número de dispositivo de 32 bits, em que 12 indica um elevado número de dispositivo mestre, 20 representa um número menor inferior
Use ls / dev / led dispositivo de visualização -l, as seguintes informações podem ser obtidas
a raiz-RW. 1 ---- CRW 0 10, 131. 1 12:00 Janeiro / dev / LED
. 1
em que 10, 131 designa um número de dispositivo, o número 10 indica o dispositivo mestre, menor número 131 denota
Para facilitar a compreensão, podemos considerar que existe um personagem do dispositivo do conjunto do kernel para o número de índice dispositivo mestre, o próprio dispositivo é um elemento array de caracteres, há um personagem conjunto de operações de arquivo de dispositivo, uma série de operações função definidos (por exemplo led_open, led_write, led_read)
chamadas de sistema sys_open para encontrar uma boa variedade de equipamentos pelo arquivo mestre, um conjunto de chamadas para o driver está led_open liderado por uma operação de arquivo de dispositivo de caractere e outras funções
driver de dispositivo de caracteres é melhorar as almofadinhas (arquivo de conjunto de operação), e em seguida, especifique o número do dispositivo, até o dispositivo de caracteres do kernel
Em terceiro lugar, o dispositivo de caracteres registrados
primeiro olhar para o objeto de dispositivo de caractere
file_operations struct {
ssize_t (* Leia) (struct arquivo *, char __user *, size_t, loff_t *);
int (* aberto) (struct inode *, struct arquivo *);
...
};
struct o cdev {
struct o kobject Kobj;
struct Module1 * proprietário; / * Ver Módulo * /
const struct os file_operations * OPS; operações / arquivo * definido * /
struct a Lista list_head;
o dev dev_t; / * número de dispositivo * /
unsigned int count;
};
em que os membros dev_t definir um número de dispositivo de 32 bits, de alta resolução dispositivo mestre 12, 20 para o número de sub-dispositivo inferior
Kernel dois seguintes maior e menor número de macro obter
MAJOR (dev_t dev) // maior número
menor (dev_t dev) // menor número
usando o seguinte número de dispositivo macro aquisição
Mkdev (int maior, menor int)
cada dispositivo tem seu próprio caráter dispositivo gama número correspondente, aqui está como aplicar o número do dispositivo
Nenhum equipamento de aplicação
alocação dinâmica
Esta função especifica o número de vezes que um número de dispositivo e o número de dispositivo pode ser atribuído dinamicamente número grande
* /
* Dev: aplicação para o número de dispositivo devolvido
baseminor *: começando número menor
* Contagem: o número do dispositivo de aplicação de número
* /
alloc_chrdev_region int (a dev_t * dev, sem sinal baseminor, sem sinal COUNT,
const char * nome)
atribuição estática
Esta função deve ser o número de número maior e menor e número do dispositivo
/ *
* De: Na verdade número do dispositivo
* Contagem: o número de número de dispositivo
* /
register_chrdev_region int (do dev_t, COUNT não assinado, const char * name)
após a conclusão do número dispositivo de aplicação, você pode usar este número de dispositivo para registrar um dispositivo de caractere
dispositivo de caracteres Register
Função e equipamentos relacionados com o personagem
vazio cdev_init (struct o cdev *, struct os file_operations *);
struct o cdev * cdev_alloc (void);
cdev_put vazio (struct o cdev * P);
cdev_add int (struct o cdev *, o dev_t, sem sinal);
cdev_del vazio (struct o cdev *);
cdev_init : FOPS e equipamento associado com o carácter utilizado, que é uma operação de arquivo file_operations definidos, é proporcionada uma série de funções de manipulação (por exemplo, aberto, lido, de gravação)
cdev_alloc: atribuir um objeto de dispositivo de caractere
cdev_add: dispositivo de caracteres Registro
cdev_del: cancelamento de um dispositivo de caractere
Um passo de registrar dispositivo de caractere
struct cdev * cdev_alloc (void); // dispositivo de caracteres atribuir
cdev_init void (struct cdev *, file_operations struct *); // vincular um fops
int cdev_add (struct cdev *, dev_t , não assinado); // caráter e para aplicar ao dispositivo o número dispositivo registrado no kernel
seguinte é um driver de dispositivo de caracteres simples
mydev.c
#include <linux / module.h>
#include <linux / init.h>
#include <linux / fs.h>
#include <linux / cdev.h>
#include <linux / slab.h>
dev_id dev_t estática;
struct cdev estática * mydev;
ssize_t mydev_read (struct arquivo * arquivo, char * __user dados, tamanho size_t, loff_t * loff)
{
printk ( "mydev_read \ n");
return 0;
}
ssize_t mydev_write (struct arquivo * arquivo, char const __user * dados, tamanho size_t, loff_t * loff)
{
printk ( "mydev_write \ n");
return 0;
}
int mydev_open (struct inode * inode, arquivo struct arquivo *)
{
printk ( "mydev_open \ n");
return 0;
}
/ *文件操作集合* /
static struct file_operations mydev_fops = {
.Owner = THIS_MODULE,
.read = mydev_read,
.open = mydev_open,
.write = mydev_write,
};
int mydev_init a estática __init (void)
{
/ * número de dispositivo de aplicação * /
alloc_chrdev_region (a dev_id & ,. 1 ,. 1 "que mydev");
/ * Atribuir dispositivo de caracteres * /
que mydev cdev_alloc = ();
/ * Dispositivo de caracteres Set * /
cdev_init (que mydev, & mydev_fops);
/ * Dispositivo de caracteres Registo * /
cdev_add (mydev, dev_id, 1);
/ * Pedido de impressão para a maior e menor número de * /
o printk ( "major: D%; Menor:% D \ n-", MAJOR (a dev_id), menor (a dev_id));
return 0;
}
__exit estática mydev_exit void (void)
{
cdev_del (mydev);
kfree (mydev);
unregister_chrdev_region (dev_id, 1);
}
module_init (mydev_init);
module_exit (mydev_exit);
MODULE_LICENSE ( "GPL");
quarto lugar, o módulo compilador
escrito em após o motorista, como é que vamos compilar o driver, existem duas maneiras, uma é compilado para o kernel e drivers juntos, um está escrito no driver sozinho módulo
A segunda apresentação aqui
Os drivers são compilados como módulos necessidade de escrever Makefile
Makefile como se segue
KERN_DIR = / trabalho / linux / kernel /
todos:
fazer -C $ (KERN_DIR) M = `pwd` módulos
limpo:
fazer -C $ (KERN_DIR) M = `pwd` módulos limpo
modules.order rm -rf
obj-m + = mydev.o
onde KERN_DIR = / trabalho / linux / kernel / semente árvore representa, de acordo com a necessidade de modificar o caminho onde o seu kernel
obj-m + = mydev.o arquivo de programa para ser compilado mydev.c
fazer $ -C (KERN_DIR) módulos pwd M = mostrar um salto para a árvore fonte do kernel, compilar módulo
O Makefile e mydev.c juntos, executar make, mydev.ko módulo da unidade podem ser obtidas
Em quinto lugar, o módulo de carregamento
utilizando o módulo de condução pode ser carregado xxx.ko insmod
Uso Ismod pode ver o módulo carregado no momento
Você pode desinstalar o driver usando módulos de xxx carregado rmmod
O mydev.ko acima copiados para gerar plataforma experimental, executar mydev.ko insmod
Uma vez módulo carregado, o kernel será executado module_init (mydev_init) entrada módulo especificado, a função mydev_init, aplicamos o número do dispositivo, registrou o dispositivo de caracteres, e imprimir o número de dispositivos maiores e menores
Você pode ver as informações de impressão
Major: 250; Menor: 1
1
representa o maior número 250, menor número 1 (o que você vê podem variar)
Neste ponto, o módulo foi carregado, podemos ver através das cat / proc / dispositivos que temos registrado o dispositivo de caractere
Mas não gerou nós de dispositivos, ainda não somos capazes de operar o equipamento no diretório / dev, aqui está como criar um nó de dispositivo
Seis, criar nós de dispositivo
criar um nó de dispositivo é criado automaticamente e manualmente criada é dividido nas seguintes foram introduzidos
criar manualmente
Nos melhores pilotos para imprimir maior: 250; menor: 1, podemos usar essa informação para criar nós de dispositivos
Até o seguinte comando para criar um nó de dispositivo
mknod nome do dispositivo tipo de dispositivo (personagem: C, bloco: b) número grande a partir do número do dispositivo
realizada
mknod / dev / mydev c 250 um
prazo após a geração do dispositivo de nó / dev / mydev
Criado automaticamente
Ele é criado automaticamente usando mecanismo udev mdev ou mecanismos, quando o controlador de dispositivo cria informações relacionadas / sys, MDEV udev ou dispositivo nodos são criados de acordo com as informações
O seguinte descreve como criar nós de dispositivos
classe struct estática * mydev_class;
mydev_class = class_create (THIS_MODULE, "mydev "); // Criar uma classe
device_create (mydev_class, NULL, dev_id, NULL, "mydev"); // criar um dispositivo de nó de acordo com o número do dispositivo
nó dispositivo destruição
device_destroy (mydev_class, dev_id); // nó dispositivo é destruído
class_destroy (mydev_class); // destruição classe
condução modificados
mydev.c
#include <linux / module.h>
#include <linux / init.h>
#include <linux / fs.h>
#include <linux / cdev.h>
#include <linux / slab.h>
#include <linux / device.h>
dev_id dev_t estática;
struct cdev estática * mydev;
classe struct estática * mydev_class;
ssize_t mydev_read (struct arquivo * arquivo, char * __user dados, tamanho size_t, loff_t * loff)
{
printk ( "mydev_read \ n");
return 0;
}
ssize_t mydev_write (struct arquivo * arquivo, char const __user * dados, tamanho size_t, loff_t * loff)
{
printk ( "mydev_write \ n");
return 0;
}
int mydev_open (struct inode * inode, arquivo struct arquivo *)
{
printk ( "mydev_open \ n");
return 0;
}
estática struct file_operations mydev_fops = {
.Owner = THIS_MODULE,
.read = mydev_read,
.open = mydev_open,
.write = mydev_write,
};
int mydev_init a estática __init (void)
{
/ * número de dispositivo de aplicação * /
alloc_chrdev_region (a dev_id & ,. 1 ,. 1 "que mydev");
/ * Atribuir dispositivo de caracteres * /
que mydev cdev_alloc = ();
/ * Dispositivo de caracteres Set * /
cdev_init (que mydev, & mydev_fops);
/ * Dispositivo de caracteres Registo * /
cdev_add (mydev, dev_id, 1);
/ * Pedido de impressão para a maior e menor número de * /
o printk ( "major: D%; Menor:% D \ n-", MAJOR (a dev_id), menor (a dev_id));
mydev_class = class_create (THIS_MODULE, "mydev");
device_create (mydev_class, NULL, dev_id, NULL, "mydev");
return 0;
}
__exit estática mydev_exit void (void)
{
device_destroy (mydev_class, dev_id);
class_destroy (mydev_class);
cdev_del (mydev);
kfree (mydev);
unregister_chrdev_region (dev_id, 1);
}
module_init (mydev_init);
module_exit (mydev_exit);
MODULE_LICENSE ( "GPL");
módulo recompilação carregado
Ver / sys / dev / char diretório, você vai encontrar mais algumas informações 250: 1
Neste ponto ver ls / dev / mydev, você vai encontrar o diretório / dev já tem um mydev
Sete teste
após cada motorista está terminado, você precisa testes de aplicativos de gravação
Aqui é o nosso programa de teste
mydev_test.c
#include <stdio.h>
#include <sys / types.h>
#include <sys / stat.h>
#include <fcntl.h>
#include <unistd.h>
int principal (int argc, char * argv [])
{
int val = 1;
int fd = open ( "/ dev / mydev", O_RDWR);
write (fd, & val, sizeof (val));
read (fd, & val, sizeof (val));
0 retorno;
}
compilado
mydev_test.c braço em Linux-gcc
módulo de carregamento
insmod mydev.ko
executar o programa de teste
./a.out
pode ver a impressão de console
[2639.832633] mydev_open
[2639.833528] mydev_write
[2639.836014] mydev_read
condutor normal, demonstrou
Este artigo para terminar aqui
----------------
Aviso: Este artigo é CSDN blogger ARTIGO ORIGINAL "estudantes JT", seguindo o CC 4.0 BY-SA acordo de direitos autorais, reimpressão Por favor, inclua links para a fonte original e esta declaração.
link original: https: //blog.csdn.net/weixin_42462202/article/details/99887783