Linux 设备驱动之init&exit
xxx_init 操作过程如下:
1.注册设备号
注册设备号即向内核申请一个设备号,一般用到
register_chrdev_region() 或者 alloc_chrdev_region()
前者为静态注册,事先知道需要用到哪个设备号,然后将其注册进入内核。后者为动态注册,即让内核自动分配一个未使用的设备号。
2.申请设备空间
xxx_devp=kzalloc(sizeof(xxx_dev),GFP_KERNEL);
在内核申请一块地址,作为该设备的空间地址。
xxx_dev这个结构体如下所示:
struct xxx_dev //定义该设备的结构体
{
struct cdev cdev;
unsigned char mem[xxx_SIZE];
};
struct cdev { //字符设备结构体
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
申请到这个空间后,需要对这个空间进行填充,初始化。
3.在地址空间中绑定fops
在刚才申请的空间中,有一个file_operations *ops; 应用层调用的所有与驱动相关的函数都出自这里,需要将这个结构体与设备进行绑定。
static const struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.read = xxx_read,
.write = xxx_write,
.unlocked_ioctl = xxx_ioctl,
.open = xxx_open,
.release = xxx_release,
};
cdev_init(&dev->cdev,&xxx_fops);//将设备和ops进行绑定
4.将设备添加进操作系统
将设备驱动所有东西准备好后,将它添加进内核。
cdev_add(&dev->cdev,devno,1); //添加一个字符设备到操作系统
xxx_exit 操作过程如下:
exit和init的操作过程是相反的,需要将之前申请过的内存释放掉,注册的设备号注销掉。
1.将设备从系统中删除
cdev_del(&globalmem_devp->cdev);
2.释放内存空间
kfree(globalmem_devp);
3.注销设备号
unregister_chrdev_region(MKDEV(globalmem_major,0),1);