[内核]Linux UserSpace和Kernel之间如何联系
转自:http://blog.csdn.net/dreaming_my_dreams/article/details/8272586
应用层和驱动的衔接,一直是一个老大难问题,若弄不清楚,总觉得驱动写起来似是而非的。下面就说说我对他们的理解,还有就是如何实现一个驱动支持多个上设备的问题。最主要涉及两个机制:inode和file
1. 在驱动中
- 我们先找到一个设备号devno,可以动态申请,也可以静态设定,假设静态设定为major,minor,通过宏MKDEV(major,minor)来生成devno
- 构建对设备的操作函数集file_opreation结构体,里面包含了的设备的操作:open、read、write、release、ioctl等
- 构建cdev结构体,里面填充两个主要成员dev(设备号)、file_operation(对设备的操作)
- 把cdev添加到cdev链表中:cdev_init、cdev_add
举个例子,tty驱动:
-->__init imx_serial_init //imx.c
-->uart_register_driver //serial_core.c
-->tty_regiser_driver //tty_io.c
-->MKDEV(driver->major, driver->minor_start) //tty_io.c
-->tty_cdev_add //tty_io.c
-->cdev_init(tty_fops) //tty_io.c, struct file_operations tty_fops={.open;.read;.write}
-->cdev_add //tty_io.c
就这样,一步步将file_operation的函数集加入到cdev->ops中,而User层则根据设备号找到cdev链表中对应的设备属性,从而找到函数集。
2. 应用程序中
fd=open("/dev/hello",O_RDWR)来打开设备文件,此设备对应有一个设备号,这是我们识别驱动和设备的桥梁。
设备号、设备文件、设备节点概念:设备号由主设备号和从设备号组成,设备号是16bit, 高8bit为主设备号,低8bit为从设备号。/dev下每个设备都有对应的设备文件,即设备节点。
打开 /dev/hello时,根据设备号,在cdev链表中找到cdev这个结构体,cdev里面包含了file_operation结构体,有设备的各种操作,打开时就调用里面的.open 函数。在这里要完成几件事:
- inode节点 每一个文件都对应有一个inode节点,inode结构体里.i_fop由cdev的file_operation填充,i_dev由cdev的设备号填充
- file结构体中的file_operation也同样由cdev中对应项填充,还有一项fd,对应于打开文件的文件描述符,fd和file一一对应,文件每打开一次,就有一个file结构。所以file里面的.private就很重要,下面会说到。
还有一个问题,那就是多个相同的设备,会公用同一个驱动(一个驱动文件1个主设备号如uart),所以要把每一个设备的私有数据封装起来,构成一个私有数据结构体。对设备的每一次读写,都通过操作设备的私有数据结构体中的资源来完成。也就是说,驱动在加载的时候,会申请多个设备私有资源结构体,每个结构体中包含了设备的所有私有资源,虽然公用一个驱动,可是通过设备号找到此设备号对应设备的私有资源,说的有点拗口。这可以通过file结构体的.private来指向。
例如封装私有数据的结构体为:
struct hello_device{
char buf[128]; //设备的私有资源,譬如buf
struct cdev cdev;//设备结构体,里面有devno和file_operation
……
};
前面应经提到inode中的i_cdev会指向cdev结构,所以可以由Container宏来得到hello_device的地址。
所以,在驱动的open函数中有两个参数,inode和file
int open(structc inode *inode,struct file *file){
struct hello_device *p =container(inode->i_cdev,hello_struct,cdev)
file->private=p;
}
这样file中就包含了设备的私有数据。
驱动read函数中:
ssize_t read(fd,char __user *buf,count)
fd和file一一对应,每打开一次设备,虽然有不同的fd,但他们的file.private是一样的。
每打开一个设备文件,把私有数据和file绑定,这样后面的read/write操作,由于fd和file一一对应,这样,read/write也就通过fd句柄就可以访问到file->private数据了。
前面主要说了一个驱动如何可以支持多个设备的问题,以及应用层和驱动之间的联系。还有一个问题就是,如何处理过多个进程访问同一个设备的问题。
-----------------------------------------------------------------------------------------------------------------------------------------------------------
转自:http://blog.chinaunix.net/uid-20543672-id-3203690.html
最近在看《深入Linux设备驱动程序机制》,这本书条理清晰,我从中获益良多。以前在学习内核驱动的时候就是知道怎么用,对于内部的原理了解的不是这么深入。且当时的能力有限,想了解深入也不容易。这次正好趁复习驱动原理的机会,把这本书认真学习以下。