Linux 字符设备驱动开发详解:cdd_demo 示例
Linux 字符设备驱动开发详解:cdd_demo 示例
本示例代码演示了如何创建一个简单的 Linux 字符设备驱动,名为 cdd_demo。
代码解析
#define CDD_MAJOR 200
#define CDD_MINOR 0
#define CDD_COUNT 1
dev_t dev;
struct cdev cdev;
struct class *cdd_class;//设备类指针
struct device *cdd_device;//设备文件指针
int cdd_open(struct inode *inode,struct file *filp)
{
printk('enter cdd_open\n');
}
ssize_t cdd_read(struct file *filp,char __user *buf,size_t size ,loff_t loff)
{
printk('cdd_read\n');
}
ssize_t cdd_write(struct file *filp,const char __user *buf,size_t size ,loff_t loff)
{
printk('cdd_write\n');
}
long cdd_ioctl (struct file *filp,unsigned int cmd,unsigned long data)
{
printk('cdd_ioctrl\n');
}
struct file_operations cdd_fops={
.owner=THIS_MODULE,
.open=cdd_open,
.read=cdd_read,
.write=cdd_write,
unlocked_ioctl=cdd_ioctl,//oictl接口
.release=cdd_release,
}
int myinit(void)
{
int ret;
ret=alloc_chrdev_region(&dev,CDD_MINOR,CDD_COUNT,'cdd_demo');
if(ret<0) {printk('device init error.\n');return ret;}
cdev_init(&cdd_cdev,&cdd_fops);
ret=cdev_add(&cdd_cdev,dev,CDD_COUNT);
if(ret<0) {printk('device init error.\n');unregister_chrdev_region(dev,CDD_COUNT);return ret;}
printk('succeed.\n');
cdd_class=class_create(THIS_MODULE,'cdd_class');
if(IS_ERR(cdd_class)){
cdev_del(&cdd_cdev);
unregister_chrdev_region(dev,CDD_COUNT);
printk('class_create failed.\n');
ret=PTR_ERR(cdd_class);
return ret;}
// 4创建设备文件
cdd_device=device_create(cdd_class,NULL,dev,NULL,'cdd');
if(IS_ERR(cdd_device)){
class_destroy(cdd_class,dev);
cdev_del(&cdd_cdev);
unregister_chrdev_region(dev,CDD_COUNT);
printk('class_create faile.\n');
ret=PTR_ERR(cdd_device);
return ret;}
return 0;
}
void myExit(void)
{
device_destroy(cdd_device);// 4
class_destroy(cdd_class,dev);// 3
cdev_del(&cdd_cdev);// 2
unregister_chrdev_region(dev,CDD_COUNT);// 1
}
module_init(myinit);
module_exit(myExit);
MODULE_LICENSE('GPL');
MODULE_AUTHOR('xxxxx');
MODULE_VERSION('1.0');
MODULE_DESCRIPTION('A symbol TEST');
每行代码的功能解释:
-
定义设备号:
#define CDD_MAJOR 200: 定义主设备号为 200。#define CDD_MINOR 0: 定义次设备号为 0。#define CDD_COUNT 1: 定义设备数量为 1。
-
定义设备结构体变量:
dev_t dev: 定义设备号变量。struct cdev cdev: 定义字符设备结构体变量。struct class *cdd_class: 定义设备类指针。struct device *cdd_device: 定义设备文件指针。
-
实现设备操作函数:
cdd_open():设备打开函数。cdd_read():设备读函数。cdd_write():设备写函数。cdd_ioctl():设备 ioctl 函数。
-
定义设备文件操作结构体变量:
struct file_operations cdd_fops: 定义设备文件操作结构体变量,包含对应的函数指针。
-
实现设备初始化函数:
myinit():alloc_chrdev_region(): 分配设备号。cdev_init(): 初始化字符设备结构体。cdev_add(): 注册字符设备。class_create(): 创建设备类。device_create(): 创建设备文件。
-
实现设备退出函数:
myExit():device_destroy(): 销毁设备文件。class_destroy(): 销毁设备类。cdev_del(): 删除字符设备。unregister_chrdev_region(): 注销设备号。
-
定义模块初始化和退出函数:
module_init(myinit): 定义模块初始化函数。module_exit(myExit): 定义模块退出函数。
-
定义模块信息:
MODULE_LICENSE('GPL'): 定义模块许可证类型。MODULE_AUTHOR('xxxxx'): 定义模块作者。MODULE_VERSION('1.0'): 定义模块版本。MODULE_DESCRIPTION('A symbol TEST'): 定义模块描述。
总结
本示例代码展示了如何创建、注册和使用 Linux 字符设备驱动,为开发者提供了一个基础框架,可以根据实际需要进行扩展和修改。
原文地址: https://www.cveoy.top/t/topic/oUw9 著作权归作者所有。请勿转载和采集!