感觉学好驱动的基础,起码要了解驱动编写过程。。。所以就小小的整理了一下。
字符设备驱动的编写
编写字符设备驱动主要完成以下动作:
1. 定义一个结构体static struct file_operations变量,其内定义一些设备的open read write close等控制函数
2. 在结构体外分别实现结构体中定义的这些函数
3. 向结构体中注册或删除驱动模块
注册字符设备:
1. 分配cdev: struct cdev *cdev_alloc(void);
2. 初始化cdev: void cdev_init(struct cdev *cdev, const struct file_operations *fops);
3. 添加cdev: int cdev_add(struct cdev *p, dev_t dev, unsigned count)
初始化时
MKDEV 创建设备号
注册设备号 通过调用register_chrdev_region()函数实现
初始化设备号 调用cdev_init()
注册设备到内核 调用cdev_add()
退出时
删除设备 调用cdev_del()
注销设备号 调用unregister_chrdev_region()
代码如下,亲测有效
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h> //struct file_operations
#include <linux/cdev.h> //struct cdev
#define NUM_OF_MINORS 1
#define HELLO_MAJOR 250
#define DEV_NAME "hello_char_dev"
static struct cdev hello_cdev;
dev_t hello_devno;
static int hello_open(struct inode *pinode, struct file *pfile)
{
printk(KERN_INFO "[kernel info]%s \n", __func__);
return 0;
}
static struct file_operations hello_ops = {
.open = hello_open,
};
static int __init hello_init(void)
{
int ret;
//组装设备号
hello_devno = MKDEV(HELLO_MAJOR, 0);//(HELLO_MAJOR << 20 | 0);
ret = register_chrdev_region(hello_devno, NUM_OF_MINORS, DEV_NAME);
if (ret < 0) {
printk(KERN_ERR "[kernel err]%s: register_chrdev_region failed! \n",
__func__);
return ret;
}
//初始化设备
//hello_cdev.ops = &hello_ops;
cdev_init(&hello_cdev, &hello_ops);
//注册设备到内核
ret = cdev_add(&hello_cdev, hello_devno, NUM_OF_MINORS);
if (ret < 0) {
printk(KERN_ERR "[kernel err]%s: cdev_add failed! \n",
__func__);
unregister_chrdev_region(hello_devno, NUM_OF_MINORS);
return ret;
}
printk(KERN_INFO "[kernel info]%s \n", __func__);
return 0;
}
static void __exit hello_exit(void)
{
cdev_del(&hello_cdev);
unregister_chrdev_region(hello_devno, NUM_OF_MINORS);
printk(KERN_INFO "[kernel info]%s \n", __func__);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jason");
MODULE_DESCRIPTION("this is the simplest module");