字符设备驱动编写流程以及大概框架

Linux设备驱动:
Linux设备驱动分为以下三类:
(1)字符设备:键盘,打印机
(2)块设备:硬盘,NAND
(3)网络设备:网卡


对于字符设备是最基本,最常见的设备:
对字符设备的驱动主要完成以下动作:
1、定义一个结构体static struct file_operations变量,其内定义一些设备的open,read,write,close等控制函数
2、在结构体外分别实现结构体中定义的这些函数
3、向内核中注册或删除驱动模块


块设备与字符设备的驱动结构是不同的,但是对于用户来说没有什么区别,块设备比字符设备要复杂,在I/O操作上极为不同表现在缓冲,I/O调度,请求队列等。
1、操作的硬件接口实现不一样;
2、数据块的数据有一定的格式


网络设备不同于字符和块设备,但是有字符和快设备的部分功能


字符设备注册有两种方式,可以以混杂设备注册:


字符设备步骤:
(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)


在2.6版本之前字符设备注册方式:
int register_chrdev(unsigned int major,const char*name,struct file_operations *fops);
其中参数major如果等于0,则表示采用系统动态分配的主设备号;不为0,则表示静态注册。
major 是感兴趣的主设备号, name 是驱动的名子(出现在 /proc/devices), fops 是缺省的 file_operations 结构. 
一个对 register_chrdev 的调用为给定的主编号注册 0 - 255 的次编号,并且为每一个建立一个缺省的 cdev 结构. 
使用这个接口的驱动必须准备好处理对所有 256 个次编号的 open 调用( 不管它们是否对应真实设备 ), 
它们不能使用大于 255 的主或次编号.register_chrdev函数的major参数如果等于0,则表示采用系统动态分配的主设备号。
它所做的事情为:
(1). 注册设备号, 通过调用 __register_chrdev_region()
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个字符设备驱动程序的典型框架: ```c #include <linux/module.h> // 模块相关头文件 #include <linux/fs.h> // 文件操作相关头文件 #include <linux/cdev.h> // 字符设备相关头文件 #include <linux/uaccess.h> // 用户空间和内核空间数据传输相关头文件 #define DEVICE_NAME "mychardev" // 设备名称 #define BUF_LEN 80 // 缓冲区大小 static int major; // 主设备号 static int minor; // 次设备号 static struct cdev cdev; // 字符设备结构体 static char buffer[BUF_LEN]; // 缓冲区 // 打开设备 static int mychardev_open(struct inode *inode, struct file *filp) { // TODO: 打开设备的操作 return 0; } // 释放设备 static int mychardev_release(struct inode *inode, struct file *filp) { // TODO: 释放设备的操作 return 0; } // 读设备 static ssize_t mychardev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { // TODO: 读设备的操作 return 0; } // 写设备 static ssize_t mychardev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { // TODO: 写设备的操作 return 0; } // 字符设备操作集合 static struct file_operations mychardev_fops = { .owner = THIS_MODULE, .open = mychardev_open, .release = mychardev_release, .read = mychardev_read, .write = mychardev_write, }; // 加载模块 static int __init mychardev_init(void) { int ret; // 申请主设备号 ret = alloc_chrdev_region(&major, minor, 1, DEVICE_NAME); if (ret < 0) { printk(KERN_ERR "Failed to allocate major number\n"); return ret; } // 初始化字符设备 cdev_init(&cdev, &mychardev_fops); cdev.owner = THIS_MODULE; // 添加字符设备 ret = cdev_add(&cdev, MKDEV(major, minor), 1); if (ret < 0) { printk(KERN_ERR "Failed to add cdev\n"); unregister_chrdev_region(MKDEV(major, minor), 1); return ret; } printk(KERN_INFO "mychardev loaded\n"); return 0; } // 卸载模块 static void __exit mychardev_exit(void) { // 删除字符设备 cdev_del(&cdev); // 释放主设备号 unregister_chrdev_region(MKDEV(major, minor), 1); printk(KERN_INFO "mychardev unloaded\n"); } module_init(mychardev_init); module_exit(mychardev_exit); MODULE_AUTHOR("Your Name"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Character device driver"); ``` 在这个框架中,我们定义了四个设备操作函数:打开设备、释放设备、读设备和写设备。同时,我们还定义了字符设备的操作集合,并在模块加载时通过调用 `alloc_chrdev_region`、`cdev_init` 和 `cdev_add` 函数来注册字符设备。在模块卸载时,我们通过调用 `cdev_del` 和 `unregister_chrdev_region` 函数来注销字符设备
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值