Linux学习(3)应用程序与驱动程序是如何连接的?

首先看一张韦东山老师给出的系统图:

Linux学习(3)应用程序与驱动程序是如何连接的?_第1张图片


在驱动开发过程中,首先是编写驱动代码。对于字符设备驱动的框架,可以归纳如下:

1,写出具体驱动函数,如 led_open(),led_read(),led_write()等

 static int first_drv_open(struct inode *inode, struct file *file)
{
//printk("first_drv_open\n");
/* 配置GPF4,5,6为输出 */
*gpfcon &= ~((0x3<<(4*2)) | (0x3<<(5*2)) | (0x3<<(6*2)));
*gpfcon |= ((0x1<<(4*2)) | (0x1<<(5*2)) | (0x1<<(6*2)));
return 0;
}

2、定义一个file_operation()函数,它指向具体的驱动函数,为下一步注册到内核提供参数。

 如:static struct file_operationsfirst_drv_fops = {
               .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
              .open     =   first_drv_open,     
        .write   =first_drv_write,   
};

3、编写入口函数,在入口函数中利用 register_chrdev()将驱动注册到内核。

 static int first_drv_init(void)
{
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核


firstdrv_class = class_create(THIS_MODULE, "firstdrv");


firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */


gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
gpfdat = gpfcon + 1;


return 0;
}

4、编写 module_init(first_drv_init); 在加载内核是调用该函数。相应的有出口函数和卸载模块的函数。

static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv"); // 卸载


class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
iounmap(gpfcon);
}


module_exit(first_drv_exit);


5、其他信息 主要是

MODULE_LICENSE("GPL");


驱动程序完成,现在分析应用程序是如何调用的

在 APP中 有open("/dev/XXX")其中dev为设备属性 字符设备为C,XXX为设备号,我们在编写驱动程序时,在编写register()函数时,有个参数为设备号major = register_chrdev(0, "first_drv", &first_drv_fops),该设备号就是为了APP认识它为做准备的。驱动在注册到内核之后,在内核中会生成一个数组,数组里面为各个设备号以及其对应的驱动操作的调用函数。通过这个 数组,就将APP层与驱动层联系起来了。



你可能感兴趣的:(嵌入式开发)