应用层如何内核.md
1.从应用层打通内核:驱动
首先来说是设备号的引入,我们通过 cat/proc/kallsyms |grep mydevice 可以查看设备号,当然我们也是可以自己创建设备号,这是源于我们在写内核模块的时候在程序中指定。设备号有了,他就可以标识我们具体的设备。那我们应用层如何操作那?其实我们应用层需要创建一个设备节点文件创建的方法是sudo mknod /dev/hello c 255 0 这样我们就可以创建一个指定设备号的设备节点文件。通过设备号,使设备节点文件和内核中的设备驱动程序关联了起来。这其实也就打通了。有了文件,我们应用层就可以用open啊,read啊去操作这个设备节点文件。真正体现了linux下一切皆文件啊!。
2.具体实现:
用户空间通过mknod创建了一个设备文件hello(设备号) 对应在内核空间创建一个inode结构体(包含有设备号)与之对应
应用程序打开这个设备文件: 操作inode结构体,取出inode里面的设备号 ==》 到内核的cdev链表中去查找这个设备号对应的cdev对象 ==》 找到
cdev对象里面的fops ===》 找到fops里面的open函数指针 ==》 这个函数指针指向我们自己实行的open函数。
3.实现一个驱动服务于多个设备:
按照以前的思路:我们现在如果是一个服务,服务于多个设备,那么问题就来了,显然我们是不会写多个驱动程序的,但是有些数据是我们必须要有多份的。比如我们现在拿最简单
的一个操作,我们在驱动程序里面注册俩个设备号,那么意味着我们在用户空间,有俩个设备节点文件,我们在应用程序中打开俩份,都采用写入的方式,写数据,如果内核中我们把
接受数据的缓冲区没有重新备份,公用一份,结果就是数据的覆盖。这些存储的数据显然是要区分的,那个设备就是那个设备,既然是服务于多设备,那设备号的创建也自然是创建多个
注册多个,这些都可以非常容易的指定,具体可以看代码以及cdev显然也是俩份,他们都在内核的链表中,但是注意cdev结构体中的fops指针都指向的是同一个,所以fops是使用的同一个
其实也很好理解fops里面都是些读写操作的函数指针,没必要区分。共用更加好。
,对于cdev还比较简单,我们在创建自己的cdev结构体的时候,指定参数就可以多创建。
最后我们干脆把这些都要用到的东西打包个结构体,叫做设备结构体。我们