Chinaunix首页 | 论坛 | 博客
  • 博客访问: 264880
  • 博文数量: 52
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 277
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-09 10:57
文章分类

全部博文(52)

文章存档

2016年(52)

我的朋友

分类: LINUX

2016-08-31 14:01:38

        学习Linux驱动必须清楚的知道这几个重要的数据结构:struct file_operations  , struct file ,  struct inode。先简单说一下它们的作用,然后再具体分析。struct file_operations 这个结构体是一个函数指针的集合,定义了能在设备上进行的操作,比如打开、关闭、读、写等等。struct file 这个结构体代表一个打开的文件,打开这个文件几次这个结构体就被创建几次,例如A,B,C都打开file1.c,则file1.c的file  struct 这个结构体会被创建三次。而struct inode 这个结构体是用来记录文件物理上的信息,不管文件被打开几次它只有一个。下面来具体分析一下这几个结构体:

        首先来说一下struct file_operations. 这个结构体的定义在头文件linux/fs.h中,它是把一个字符设备的驱动和设备号联系起来的纽带,我们都知道调用一个函数就需要知道它的入口地址,同样的设备驱动也是一系列的函数组成的,要运行设备驱动就要知道其中函数的入口地址,而结构体file_operations 就记录了设备驱动中的一系列函数的入口地址,是一系列函数指针的集合。每个系统调用都对应着这个函数中的一个指针,当用户进行系统调用的时候,就相当于找到了对应驱动程序的入口,然后就把控制权交给驱动程序了,驱动程序就运行起来了。下面是我在内核中找到的这个结构体。
                            

    至于这个结构体中的每个函数的具体的意思,用兴趣的可以百度一下。内核中的驱动模块是不需要实现每个函数的,对于不需要实现的函数只需其对应的项为空(NULL)即可,在通读函数列表时,你会发现有不少函数的参数中有__user *,这种注解是一种文档形式,注意,这个指针是不能被直接引用的用户地址空间,需要做相应的转换才能被内核的代码引用,因为用户指针在内核时可能是无效的,即没有那个地址的映射。对于正常的编译,__user 是无效的,不过它可以被外部检查软件使用来找出用户空间地址的错误使用。

    gcc还有这个结构体使用的扩展结构体,你可以在较现代的驱动模块中找到。新的扩展结构体使用如下(只写部分成员):
                                    struct  file_operations fops={
                                              read : xx_read;
                                              write : xx_write;
                                              open : xx_open;
                                              release : xx_release;
                                              ...};

    同样也有C99语法使用该结构体的方法,并且它比GUN的扩展更受推荐推荐使用这种,语法清晰,且可以提高兼容性(只写部分成员):
                                    struct  file_operations fops={
                                              .read = xx_read;
                                              .write = xx_write;
                                              .open = xx_open;
                                              .release = xx_release;
                                              ...};

         下面来说一下struct file ,系统每打开一个文件在内核中都有一个关联的struct file ,它不是专门给驱动程序使用的,它由内核在open时创建,并传递给在文件上操作的任何函数,例如打开int (* open) (struct inode *inode, struct file * file ),读,写等。直到最后关闭,当文件的所有实例都关闭后(struct file 中有一个变量来记录文件被使用的次数,当为0时,就可释放了),内核就释放这个数据结构,具体内容如下:
                        
                        
这个数据结构主要是记录文件的一些打开的信息,比如读还是写的方式打开,打开后的操作等等,正如开始所说的,同一个文件被打开N次,则会创建N个struct file,因为打开时的一些方式不同,就比如上图中的  const struct file_operations *f_op所赋予的值(操作)不同,f_flags不同等等。中间有一个非常值得注意的   void  *private_data ,这个成员比较特殊,内核本身不会读写这个成员,而是预留给驱动使用的。一般来说,驱动要为内个设备建立一些变量,用以保存一些必要的数据,称为设备的私有数据。这些数据可以包装成一个结构体,然后把结构体的指针赋值给private_data成员,这个就把设备的数据和打开的文件联系到一起了。

        最后说一下struct inode 。
 inode 译成中文就是索引节点。每个存储设备或存储设备的分区(存储设备是硬盘、软盘、U盘 ... ... )被格式化为文件系统后,应该有两部份,一部份是inode,另一部份是Block,Block是用来存储数据用的。而inode呢,就是用来存储这些数据的信息,这些信息包括文件大小、属主、归属的用户组、读写权限等。inode为每个文件进行信息索引,所以就有了inode的数值。操作系统根据指令,能通过inode值最快的找到相对应的文件。 
      做个比喻,比如一本书,存储设备或分区就相当于这本书,Block相当于书中的每一页,inode 就相当于这本书前面的目录,一本书有很多的内容,如果想查找某部份的内容,我们可以先查目录,通过目录能最快的找到我们想要看的内容。具体内容如下:
                        
                        

如果还有什么疑问,可以看我的下一篇文章,下篇文章会用一个具体的实例,来说一下字符设备的驱动,以及这几个函数。嘿嘿!



阅读(1713) | 评论(0) | 转发(0) |
0

上一篇:Ubuntu 下安装及使用Ctags

下一篇:零碎知识

给主人留下些什么吧!~~