[Desenvolvimento e aprendizado do driver IMX6ULL] 06. Dados de transferência de aplicativo e driver + criação automática de nós de dispositivo (hello driver)

1. Transfira dados entre o APP e o motorista

/*驱动从APP获取数据*/
unsigned long copy_from_user(void *to, const void *from, unsigned long n)

/*驱动传输数据到APP*/
unsigned long copy_to_user(void *to, const void *from, unsigned long n)

2. Use copy_to_user e copy_from_user para transferir dados entre o APP e o driver hello

método de teste:

./hello_test /dev/hello 1234abc    APP向驱动程序写入数据
./hello_test /dev/hello            APP从驱动程序读出刚才写入的数据

Princípio de dados de transferência de aplicativo e motorista:

  1. O APP chama a função open para abrir o dispositivo e usa a função IO do sistema para gravar dados no dispositivo
  2. O sistema chama a função de operação de gravação do driver (especificada pela estrutura file_operations) e passa os parâmetros passados ​​no APP para a função de operação de gravação
  3. A função de operação de gravação do programa do driver chama a função copy_from_user para copiar dados do programa do usuário para o programa do driver
  4. APP chama a função IO do sistema lida para ler os dados da unidade
  5. O sistema chama a função de operação de leitura do driver (especificada pela estrutura file_operations) e copia os dados do driver para o APP

Vamos representá-lo com uma imagem
insira a descrição da imagem aqui

3. O driver cria nós de dispositivo automaticamente

A primeira etapa: função class_create para criar uma classe de dispositivo

/*
 * @description		: 创建一个class类型的对象
 * @param - owner	: THIS_MODULE
 * @param - name	: 类名字
 * @return 			: 成功,返回struct class的指针;其他 失败
 */
struct class *class_create(struct module *owner, const char *name)

/*举例*/
static struct class *hello_class;
hello_class = class_create(THIS_MODULE, "hello_class");

Etapa 2: A função device_create cria um nó de dispositivo em /dev (não há necessidade de executar o comando mknod no lado da placa de desenvolvimento)

/*
 * @description		: 生成设备节点并导出到用户空间(在/dev下创建设备节点)
 * @param - class	: 指向该设备应注册到的struct class的指针(上一个class_create函数返回值)
 * @param - parent	: 指向此新设备的父struct设备的指针(如果有),没有填NULL
 * @param - devt	: 要添加的char设备的dev_t(设备号)
 * @param - drvdata	: 要添加到设备中以进行回调的数据(如果有),没有填NULL
 * @param - fmt		: 设备名称的字符串
 * @return 			: 成功,返回struct device指针;其他 失败
 */
struct device *device_create(struct class *class, struct device *parent, 
								dev_t devt, void *drvdata, const char *fmt, ...)
/*举例*/
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");

O código acima,
olá, código do driver:

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/capability.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/therm.h>
#include <linux/string.h>


static int major;
static unsigned char buff[100];
static struct class *hello_class;

static int hello_open (struct inode *node, struct file *filp)
{
    
    
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	return 0;
}

static ssize_t hello_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
    
    
	size_t len = size > 100 ? 100 : size;
	printk("hello_read\n");
	copy_to_user(buf, buff, len);
	return len;
}

static ssize_t hello_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
    
    
	size_t len = size > 100 ? 100 : size;
	memset(buff, 0 ,sizeof(buff));
	printk("hello_write\n");
	copy_from_user(buff, buf, len);
	return len;
}

static int hello_release (struct inode *node, struct file *filp)
{
    
    
	printk("hello_release\n");
	return 0;
}

/*1.定义 file_operations 结构体*/
static const struct file_operations hello_drv = {
    
    
    .owner 		= THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
	.release    = hello_release,
};

/*3.入口函数*/
static int hello_init(void)
{
    
    
	//返回主设备号
	major = register_chrdev(0,"hello_drv",&hello_drv);
	
	printk("hello_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	/*在内核中创建设备*/
	hello_class = class_create(THIS_MODULE, "hello_class");
	if (IS_ERR(hello_class)) {
    
    
		printk("hello class create failed!\n");
	}

	/*在设备类下面创建设备*/
	device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");
	if (IS_ERR(dev)) {
    
    
		printk("hello device_create  failed!\n");
	}
	return 0;
}

/*4.退出函数*/
static int hello_exit(void)
{
    
    
	//卸载设备
	unregister_chrdev(major,"hello_drv");

	//销毁设备
	device_destroy(hello_class, MKDEV(major, 0));
	//删除设备类
	class_destroy(hello_class);

	//删除注册的设备号
	// unregister_chrdev_region(major, 1);

	return 0;
}	

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

Olá código do aplicativo:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
    
    
    int len;
    char read_buf[10];

    if(argc < 2){
    
    
        printf("please input  at least 2 args\n");
        printf("%s <dev> [string]\n", argv[0]);
        return -1;
    }

    /*open*/
    int fd;
    fd = open(argv[1], O_RDWR);
    if(fd < 0){
    
    
        printf("open failed\n");
        return -2;
    }

    /*read*/
    if(argc == 2){
    
      
        read(fd, read_buf, 10);    //调用read函数,只为了触发系统调用hello驱动的read函数
        printf("read operation : %s\n", read_buf);
    }

    /*write*/
    if(argc == 3){
    
    
        len = write(fd, argv[2], strlen(argv[2]));   //调用write函数,只为了触发系统调用hello驱动的write函数
        printf("write length = %d \n", len);
    }

    close(fd);

    return 0;
}

Resultado dos testes:

[root@100ask:/mnt]# insmod hello_drv.ko  (向内核注册hello驱动)
[root@100ask:/mnt]# cat /proc/devices    (查看驱动设备号)
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 81 video4linux
 89 i2c
 90 mtd
108 ppp
116 alsa
128 ptm
136 pts
166 ttyACM
180 usb
188 ttyUSB
189 usb_device
207 ttymxc
216 rfcomm
226 drm
238 hello_drv
[root@100ask:/mnt]# ls -l /dev/hello       (查看/dev下是否有hello设备节点)
crw------- 1 root root 238, 0 Jan  1 01:37 /dev/hello

#测试hello驱动读写操作
[root@100ask:/mnt]# ./hello_test /dev/hello 1234abc    (向驱动写)
write length = 7 
[root@100ask:/mnt]# ./hello_test /dev/hello            (读驱动)
read operation : 1234abc

Acho que você gosta

Origin blog.csdn.net/HuangChen666/article/details/131134366
Recomendado
Clasificación