字符设备是 3 大类设备(字符设备、块设备和网络设备)中较简单的一类设备,其驱动程序中完成的主要工作是初始化、添加和删除 cdev 结构体,申请和释放设备号,以及填充file_operations结构体中的操作函数,实现file_operations结构体中的read()、write()和ioctl()等函数是驱动设计的主体工作。
static int demo_open (struct inode *inodp, struct file *filp)
{
filp->private_data = container_of(inodp->i_cdev, struct scull_t, cdev);
return 0;
}
ssize_t demo_read (struct file *filp, char __user *buf, size_t cnt, loff_t *fpos)
{
return ;
}
ssize_t demo_write (struct file *filp, const char __user *buf, size_t cnt, loff_t *fpos)
{
return ;
}
/*由上层的close调用*/
static int demo_release (struct inode *inodp, struct file *filp)
{
return 0;
}
const struct file_operations fops = {
.owner = THIS_MODULE,
.open = demo_open,
.read = demo_read,
.write = demo_write,
.release = demo_release,
};
static int demo_init(void)
{
/*静态或动态申请注册设备号*/
if (major) {
devnum = MKDEV(major, 0);
ret = register_chrdev_region(devnum, CNT, DEVNAME);
} else {
ret = alloc_chrdev_region(&devnum, 0, CNT, DEVNAME);
major = MAJOR(devnum);
}
class_create(THIS_MODULE, DEVNAME);
cdev_init(&sculldev[i].cdev, &fops);
ret = cdev_add(&sculldev[i].cdev, devnum, 1);
/*设备文件的创建*/
device = device_create(class, NULL, devnum, NULL, "scull%d", i);
}
module_init(demo_init);
static void demo_exit(void)
{
devnum = MKDEV(major, i);
device_destroy(class, devnum);
cdev_del(&sculldev[i].cdev);
class_destroy(class);
devnum = MKDEV(major, 0);
unregister_chrdev_region(devnum, CNT);
}
module_exit(demo_exit);
MODULE_LICENSE("GPL");