作 者:道哥,10 年嵌入式开发老兵,专注于:C/C 、嵌入式、Linux。
关注下方公众号,回复【书籍】,获取 Linux、嵌入式领域经典书籍;回复【PDF】,获取所有原创文章( PDF 格式)。
目录
-
API 函数
-
编写驱动程序
-
编写应用程序
-
卸载驱动模块
-
小结
别人的经验,我们的阶梯!
大家好,我是道哥,今天我们继续讨论:
Linux 中字符设备的驱动程序。
在上一篇文章中Linux驱动实践:你知道【
字符设备驱动程序】的两种写法吗?我们说过:字符设备的驱动程序,有两套不同的API函数,并且在文中详细演示了利用
旧的API函数来编写驱动程序。
这篇文章,我们继续这个话题,
实际演示一下:
字符设备驱动程序的另一套API函数的使用方法。
API 函数
这里主要关注下面这
3 个函数:
// 静态注册设备
int register_chrdev_region(dev_t from, unsigned count, const char *name);
// 动态注册设备
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
// 卸载设备
void unregister_chrdev_region(dev_t from, unsigned count);
关于静态和动态注册,主要的区别就在于:
主设备号由谁来主导分配!
静态注册:由我们的驱动程序来指定主设备号,即参数1:from;
动态注册:由操作系统来分配,驱动程序提供一个变量来接收该设备号,即参数1: dev 指针;
另外,在Linux 2.6后期的内核版本中,引入了
cdev 结构来描述一个字符设备,它的结构体成员是:
struct cdev {
struct kobject kobj; // 内嵌的kobject对象
struct module *owner; // 所属模块
const struct file_operations *ops;//文件操作结构体
struct list_head list; // 链表句柄
dev_t dev; // 设备号
unsigned int count;
};
与这个结构体相关的处理函数有:
void cdev_init(struct cdev *,struct file_operations *);
初始化 cdev 的成员,主要是设置 file_operations。
strcut cdev *cdev_alloc(void);
动态申请 cdev 内存。
void cdev_put(strcut cdev *p);
与 count 计数相关的操作。
int cdev_add(struct cdev *,dev_t ,unsigned );
向系统中添加一个 cdev,注册字符设备,需要在驱动被加载的时候调用。
void cdev_del(struct cdev *);
从系统中删除一个 cdev,注销字符设备,需要在驱动被卸载的时候调用。
后面在代码演示的时候,可以看到cdev结构是如何被使用的。
按照惯例,我们仍然按照步骤,来讨论如何利用上述的APIs,来手写一个字符设备的驱动程序。
以下所有操作的工作目录,都是与上一篇文章相同的,即:~/tmp/linux-4.15/drivers/。
$ cd linux-4.15/drivers/
$ mkdir my_driver2
$ cd my_driver2
$ touch driver2.c
driver2.c文件的内容如下(
不需要手敲,文末有代码下载链接):
#include
#include
#include
#include
#include
static struct cdev my_cdev;
static dev_t dev_no;
int driver2_open(struct inode *inode, struct file *file)
{
printk("driver2_open is called. \n");
return 0;
}
ssize_t driver2_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
printk("driver2_read is called. \n");
return 0;
}
ssize_t driver2_write (struct file *file, const char __user *buf, size_t size, loff_t *ppos)
{
printk("driver2_write is called. \n");
return 0;
}
static const struct file_operations driver2_ops={
.owner = THIS_MODULE,
.open = driver2_open,
.read = driver2_read,
.write = driver2_write,
};
static int __init driver2_init(void)
{
printk("driver2_init is called. \n");
// 初始化cdev结构
cdev_init(
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。