6.22 驱动开发作业

news/2024/11/24 11:13:07/

字符设备驱动内部实现原理

1.字面理解解析:

字符设备驱动的内部实现有两种情况:

情况1.应用层调用open函数的内部实现:

open函数的第一个参数是要打开的文件的路径,根据这个路径 虚拟文件系统层VFS 可以找到这个文件在文件系统中唯一的标识,也就是inode号,通过inode号作为索引可以找到储存在内核中的struct inode结构体,struct inode结构体内部储存着 struct cdev结构体 和 储存该文件设备号的变量dev,因为设备文件想联系设备驱动,就要在inode结构体中保存该驱动的设备号 通过解析struct cdev结构体可知:结构体内部也有储存设备号的变量dev和操作方法结构体指针,通过操作方法结构体指针 VFS 就可以帮助我们回调对应的 mycdev_open 函数

open函数回调实现路线:

1.应用层open函数+打开路径参数 ----> 2.VFS层 --->3.对应设备文件inode号--->4.索引得 对应的struct inode结构体---> 5.struct cdev结构体---> 6.操作方法结构体、设备号---> 7.回调对应操作函数 myopen

情况2.应用层调用write/read等函数的内部实现:

write/read 函数没有指定路径的参数,换成了使用从open函数返回值得到的文件描述符来进行回调对应的操作方法 首先,当一个进程运行在操作系统中,那么就一定会在内核中的task_struct结构体空间中封存放进程的相关信息, 在task_struct结构体中, 有着存放着打开文件相关的结构体成员struct files_struct ,files_struct结构体成员struct file __rcu * fd_array[fd] 的下标 就是文件描述符的本质,这个结构体指针指向的结构体类型struct file 里就有操作方法结构体,通过文件描述符就可以确认是数组的哪个下标成员,VFS 虚拟文件系统层 来帮助我们回调对应的操作方法

read、write函数回调实现路线:

1.应用层write/read函数+fd文件描述符参数 ---> 2.VFS层---> 3.task_struct结构体--->  4.struct files_struct *files; //打开的文件相关结构体---> 5.struct file __rcu * fd_array[NR_OPEN_DEFAULT];//结构体指针数组,fd本质就是这个数组的下标---> 6.确定是数组中哪个struct file类型的成员---> 7.调用操作方法结构体成员---> 8.回调对应read、write函数

 

文件信息结构体:
struct inode
{umode_t i_mode;unsigned short i_opflags;kuid_t i_uid;kgid_t i_gid;dev_t i_rdev;union{struct block_device *i_dev;struct cdev;char *i_link;unsigned i_dir_seq;};
};字符设备驱动对象结构体:
struct cdev {struct kobject kobj;struct module *owner;//THIS_MODULEconst struct file_operations *ops;//操作方法结构体struct list_head list;//构成链表dev_t dev;//设备号unsigned int count;//设备数量
};

分步注册流程和代码实例:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/cdev.h>unsigned int major;
dev_t devno;
struct cdev *cdev;
unsigned int major=500;
unsigned int minor=0;
struct class *cls;
struct device *dev;char kbuf[128]={0};int mycdev_open(struct inode *inode, struct file *file){return 0;}ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *iof){return 0;}ssize_t mycdev_write(struct file *file, const char  *ubuf, size_t size, loff_t *iof)
{return 0;
}int mycdev_close(struct inode *inode, struct file *file)
{return 0;
}//定义一个操作方法结构体变量并且初始化
//结构体解析:需要使用一个结构体内的成员时才需要初始化这个变量的成员,
//此处需要准备4个函数初始化函数指针成员
//如果是结构体指针则需要实例化一个对应的结构体变量,或者指向函数申请的堆区空间
struct file_operations fops={.open=mycdev_open,.read=mycdev_read,.write=mycdev_write,.release=mycdev_close,
};static int __init mycdev_init(void)
{int ret,i;//1.分配字符设备驱动对象空间cdev=cdev_alloc();if(cdev==NULL){printk("分配字符设备驱动对象失败\n");ret=-EFAULT;goto LOOP1;}printk("分配对象空间成功\n");//2.字符驱动对象初始化cdev_init(cdev,&fops);//3.申请设备号//静态指定设备号if(major>0){ret=register_chrdev_region(MKDEV(major,minor),3,"myled");if(ret){printk("静态指定设备号失败\n");goto LOOP2;}}else if(major==0) //动态申请设备号{ret=alloc_chrdev_region(&devno,minor,3,"myled");if(ret){printk("动态申请设备号失败\n");goto LOOP2;}major=MAJOR(devno);minor=MINOR(devno);}printk("申请设备号成功\n");//4.添加字符设备驱动对象注册进内核ret=cdev_add(cdev,MKDEV(major,minor),3);if(ret){printk("字符设备驱动对象注册失败\n");goto LOOP3;}printk("添加字符设备驱动对象注册进内核成功\n");cls=class_create(THIS_MODULE,"myled");if(IS_ERR(cls)){printk("向上提交目录失败\n");ret=-PTR_ERR(cls);goto LOOP4;}printk("向上提交目录成功\n");//向上提交设备节点信息for(i=0;i<3;i++){dev=device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);if(IS_ERR(dev)){ret=-PTR_ERR(dev);goto LOOP5;}}return 0;LOOP5://释放已经申请的设备节点信息for(--i;i>=0;i--){device_destroy(cls,MKDEV(major,i));}//释放目录空间class_destroy(cls);LOOP4://注销字符设备驱动对象cdev_del(cdev);LOOP3://释放设备号unregister_chrdev_region(MKDEV(major,minor),3);LOOP2:kfree(cdev);    LOOP1:return ret; 
}static void __exit mycdev_exit(void)
{//销毁设备节点int i;for(i=0;i<3;i++){device_destroy(cls,MKDEV(major,i));}//释放目录空间class_destroy(cls);//注销字符设备驱动对象cdev_del(cdev);//释放设备号unregister_chrdev_region(MKDEV(major,minor),3);//释放对象空间kfree(cdev);
}module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");


http://www.ppmy.cn/news/521281.html

相关文章

STE | 扬大/基因组所-齐碳纳米孔长读长宏基因组解析蛋鸡粪便中高流行耐药基因新机制...

长读长宏基因组测序揭示高拷贝小质粒为动物粪便微生物组中高流行耐药基因关键载体 Long-read metagenomic sequencing reveals that high-copy small plasmids shape the highly prevalent antibiotic resistance genes in animal fecal microbiome Article, 2023-06-02, Scien…

C++——用红黑树封装map和set

目录 1. 前言 2. 红黑树模板参数的控制 3. 模板参数中仿函数的增加 4. 红黑树迭代器的实现 5. 红黑树的begin()和end() 6. 红黑树的Find查找函数 7. 红黑树封装map和set源码 7.1 map.h 7.2 set.h 7.3 test.cpp 1. 前言 我们都知道set是K模型的容器&#xff0c;而map…

谷歌浏览器打不开12306

因为https的原因 浏览器里输入https://dynamic.12306.cn/otsweb/ 选择继续就可以了&#xff0c;火狐也可以。

IE能够打开网页 可是chrome和火狐打不开网页解决的方法

IE能够打开网页 可是chrome和火狐打不开网页解决的方法 参考文章&#xff1a; &#xff08;1&#xff09;IE能够打开网页 可是chrome和火狐打不开网页解决的方法 &#xff08;2&#xff09;https://www.cnblogs.com/lcchuguo/p/5197053.html 备忘一下。

简单几步解决ie打不开闪退的问题 亲测有效

起因&#xff1a; 银行U盾插入 IE自动打开银行门户网站 打不开 闪退 不插入之后 IE还是闪退&#xff0c; 修复之法 清除IE扩展 一些自己安装的扩展或是被恶意安装的扩展插件会导致IE无法启动 1. 按住windowsr调出运行&#xff0c;在框中输入&#xff1a;inetcpl.cpl 点击确…

火狐打不开12306购票网站解决办法

有童鞋在打开12306网站购票时&#xff0c;会经常出现下面这个问题&#xff1a; 您想使用 Firefox 来安全连接至 dynamic.12306.cn&#xff0c;但是我们无法确认此连接为安全的。 通常&#xff0c;当您尝试安全连接时&#xff0c;站点会出示受信任的标识&#xff0c;以证明您访问…

极智经验 | win10 IE浏览器无法打开网页解决方法

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多笔记分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍一下 win10 IE浏览器无法打开网页的解决方法。 问题描述&#xff1a; win10 上 IE浏览器无法打开网页&#xff0c;但其他浏览器能正常上网。 解决方法&…

国庆回家之旅--机械男孩为什么不补卧铺?

下午5:00左右&#xff0c;列车员在走道里面&#xff0c;说有卧铺了&#xff0c;需要补的乘客可以到他工作间补卧铺。我迅速的举手示意说我补一个&#xff0c;他说到下一站樟树才能卧铺乘客下&#xff0c;现在补&#xff0c;还不能过去&#xff0c;我说没有关系&#xff0c;我现…