linux驱动入门手记

来源:互联网 发布:软件著作权申请表范文 编辑:程序博客网 时间:2024/06/04 18:32

linux驱动涉及linux内核知识,硬件知识等等相当高深领域,让我等菜鸟入门时望而兴叹。本菜记录初次编写完整驱动经验,希望以读者能看懂方式写出入门级驱动编写要点。

1.驱动程序基本结构

写普通C语言单文件程序时,都是从main()函数开始。驱动程序其实有类似的结构,即module_init(xxx_init)和module_exit(xxx_exit).这相当于main()函数入口和出口,加载时候调用入口,卸载时候调用出口。编写驱动程序即从xxx_init函数开始,到xxx_exit函数结束。驱动程序基本逻辑是设备启用时加载驱动->任由上层调用提供的接口->设备关闭时卸载驱动。提供的接口根据需求不同,但加载卸载原理大致相同。


2.加载卸载三部曲

以字符设备为例,写一个驱动加载基本的3套步骤群,步骤群都是加载和卸载对应。

(1)为设备获得编号

加载时:

dev_t devno = MKDEV(major, 0);
if (major) //user define the major number
{
ret = register_chrdev_region(devno, 1, DEV_NAME);
}
else // system alloc the major number
{
ret = alloc_chrdev_region(&devno, 0, 1, DEV_NAME);
major = MAJOR(devno);
}

if (ret < 0)
{
printk("can't get major %d) \n", major);
}

卸载时:

unregister_chrdev_region(MKDEV(major,0),1);


(2)利用udev,使驱动在加载时能在/dev下自动创建设备文件

加载时:

my_class = class_create(THIS_MODULE, "my_class");
if (IS_ERR(my_class)) {
printk("my class register failed, errno:%ld\n",
PTR_ERR(my_class));
return PTR_ERR(my_class);
}


sysfs_node = device_create(my_class, NULL, devno, NULL, "my_device");
if (IS_ERR(sysfs_node)) {
printk("WARN: device node can't create automatically,"
"errno=%ld\n", PTR_ERR(sysfs_node));
}

卸载时:

device_destroy(my_class, MKDEV(major, 0));
class_destroy(my_class);


(3)为驱动挂载对应接口

加载时:

dev->rx_timeout_second = -1; //wait forever.
sema_init(&dev->sem, 10);
cdev_init(&dev->cdev, &my_fops);
dev->cdev.owner = THIS_MODULE;
ret = cdev_add(&dev->cdev, devno, 1);
if(ret)
{
printk("cdev_add Error %d adding %d", ret, index);
return;
}

卸载时:

cdev_del(&dv_dev.cdev);


3.加载之后

所有接口都写在my_fops这个结构体里就行了,包括打开,关闭,io操作,具体还是需要深入学习file_operations结构。




原创粉丝点击