超级块、目录项、索引节点和文件对象是VFS虚拟文件系统的4个最关键组成要素,一个inode索引节点唯一的对应一个目录文件夹或者文件,比如:/home/gliethttp/hello.c,我们想打开其中的hello.c文件,open("/home/gliethttp/hello.c",O_RDWR);硬盘上home文件夹唯一对应一个属于home文件夹自己的硬inode索引节点片段信息,gliethttp文件夹也同样在硬盘上唯一对应一个属于gliethttp文件夹自己的硬inode索引节点片段信息,只不过home和gliethttp对应的硬inode索引节点片段信息表示的为文件夹,其中存储在该硬inode片段信息下数据区的内容只有一个文件名,hello.c则不同,虽然hello.c在硬盘上也有一个和hello.c自己唯一对应的硬inode索引节点片段信息,但是它的硬inode索引节点片段信息的数据区主要是用来对文件真实内容进行索引,而不像文件夹的数据区那样,仅仅用来存储文件夹的名字;open函数会通过path_walk()调用ext3_lookup()函数从硬盘中将home、gliethttp和hello.c,这三个硬inode索引节点片段信息,读出来,随后当即将这些硬inode索引节点片段信息分别重新组织,生成一个表达力更加丰富的,能够供内核使用起来得心应手的内核全功能inode索引节点【注意:ext3系统中用来存储文件的硬inode信息片段往往很简单,仅仅存储了一个文件必须的几个关键信息,内核要想方便快捷的对文件进行操作,必须在内核内存中基于硬盘上的硬inode索引节点片段,添加进若干操作属性集,比如:list链表等,重新构建一个更加复杂的,应用起来更加灵活的全功能inode索引节点,这个全功能inode索引节点以硬件inode信息片段为雏形,更加丰富快速的表达硬件inode片段信息对应的文件】.因为硬inode索引节点片段信息唯一对应一个文件夹或文件,那么基于硬inode索引节点片段信息的在内核内存中重新组建的全功能inode索引节点也唯一指向那个文件夹或文件,并且在ext3_lookup()组织全功能inode索引节点的时候内核会调用ext3_read_inode()为该inode分配操作该inode的特定操作函数集,比如dir文件夹的内存全功能inode索引节点对应的inode操作函数集和file文件对象操作函数集如下:
inode->i_op = &ext3_dir_inode_operations;
inode->i_fop = &ext3_dir_operations;
举个驱动文件样例,对于像《Linux下LED驱动测试源码》【文章地址 http://gliethttp.cublog.cn】驱动程序实例中使用到的
[root@gliethttp]# mknod /dev/led c 254 0
在/dev文件夹下建立一个字符类型的名为led的字符设备文件,ext3_read_inode()函数会在内核内存中组建led文件的全功能inode索引节点的时候调用init_special_inode()为其分配操作该字符设备inode的操作函数集inode->i_fop = &def_chr_fops;这个def_chr_fops集中只实现了一个open函数调用chrdev_open(),(结构体变量:struct file_oprations def_char_fops,以及函数dev_chr_fops()等均可在目录fs/char_dev.c中找到)
比如:《Linux下LED驱动测试(应用程序)源码》【文章地址 http://gliethttp.cublog.cn】应用程序实例中用到如下函数打开设备
fd=open("/dev/led",O_RDWR);
ext3硬盘文件系统上的文件led的硬inode索引节点片段会在函数ext3_lookup()中被重新组建到内核内存中,生成一个led文件对应的inode全功能索引节点,并调用chrdev_open()函数,chrdev_open()在执行时会调用kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);函数从所有注册登记到内核的字符设备驱动中,根据MAJOR主设备号查找led设备所用的驱动,如果找到,filp->f_op = fops_get(p->ops);那么将使用insmod led命令注册到内核的驱动程序对应的文件对象操作函数集合赋值给这个current进程对应的filp->f_op,
static struct file_operations gliethttp_led_fops={
owner: THIS_MODULE,
ioctl: led_ioctl,
open: led_open,
release:led_release,
};
所以这时filp->f_op就等于了gliethttp_led_fops,赋值之后,filp->f_op就不再是def_chr_fops了,而被字符驱动程序的gliethttp_led_fops操作集替换了,用户再次调用open,open动作也就是被导向到直接调用led_open了,以上的inode似乎已经可以勉强的解决文件的读写问题了,但对于每次进行文件打开都要进行全功能inode信息组建,着实是一个费时费力的事情,作为高性能形象代言人--linux内核,速度和高效永远是内核开发阵营响亮的营歌,也是所有用户对linux内核的强烈感觉,故而linux引入了目录项dentry,目录项使得inode可以安全的停留在内核内存中不被轻易释放掉,一个目录项唯一对应一个由ext3_lookup()函数组建到内核内存的全功能inode索引节点,而一个全功能inode索引节点可以被若干个目录项对应,这也就使得应用更加灵活,目录项通过hash算法,将成千上万的哥们儿目录项们,打散到各个hash短链中【对于hash短链的理解可以参看《其实hash哈希原理很简单 》文章地址 http://gliethttp.cublog.cn】hash短链的引入让文件查询的速度也就被成百上千倍的得到优化提升放大,迅速的找到了一个dentry也就找到了文件夹或文件对应的inode,也就迅速的找到了那个相应的文件夹或文件,也就节省了大家不少的时间.
综述:一个ext3文件系统硬盘上的硬inode索引节点片段信息,唯一的对应物理文件,这是内核内存中全功能inode索引节点存在的唯一硬件文件来源,硬inode索引节点片段信息存储在硬盘上,而全功能inode索引节点和目录项dentry都只是在内核内存中被临时组建起来,随着内核的运行,可能会被释放掉的硬盘上的文件在内核内存中的一个快速索引而已,至于file文件对象,也是一个纯内存对象,和硬盘文件无关,当然file对象和硬盘文件存在着的那点关系由file->f_op=inode->f_op文件对象操作集来勉强维系。
inode->i_op = &ext3_dir_inode_operations;
inode->i_fop = &ext3_dir_operations;
举个驱动文件样例,对于像《Linux下LED驱动测试源码》【文章地址 http://gliethttp.cublog.cn】驱动程序实例中使用到的
[root@gliethttp]# mknod /dev/led c 254 0
在/dev文件夹下建立一个字符类型的名为led的字符设备文件,ext3_read_inode()函数会在内核内存中组建led文件的全功能inode索引节点的时候调用init_special_inode()为其分配操作该字符设备inode的操作函数集inode->i_fop = &def_chr_fops;这个def_chr_fops集中只实现了一个open函数调用chrdev_open(),(结构体变量:struct file_oprations def_char_fops,以及函数dev_chr_fops()等均可在目录fs/char_dev.c中找到)
比如:《Linux下LED驱动测试(应用程序)源码》【文章地址 http://gliethttp.cublog.cn】应用程序实例中用到如下函数打开设备
fd=open("/dev/led",O_RDWR);
ext3硬盘文件系统上的文件led的硬inode索引节点片段会在函数ext3_lookup()中被重新组建到内核内存中,生成一个led文件对应的inode全功能索引节点,并调用chrdev_open()函数,chrdev_open()在执行时会调用kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);函数从所有注册登记到内核的字符设备驱动中,根据MAJOR主设备号查找led设备所用的驱动,如果找到,filp->f_op = fops_get(p->ops);那么将使用insmod led命令注册到内核的驱动程序对应的文件对象操作函数集合赋值给这个current进程对应的filp->f_op,
static struct file_operations gliethttp_led_fops={
owner: THIS_MODULE,
ioctl: led_ioctl,
open: led_open,
release:led_release,
};
所以这时filp->f_op就等于了gliethttp_led_fops,赋值之后,filp->f_op就不再是def_chr_fops了,而被字符驱动程序的gliethttp_led_fops操作集替换了,用户再次调用open,open动作也就是被导向到直接调用led_open了,以上的inode似乎已经可以勉强的解决文件的读写问题了,但对于每次进行文件打开都要进行全功能inode信息组建,着实是一个费时费力的事情,作为高性能形象代言人--linux内核,速度和高效永远是内核开发阵营响亮的营歌,也是所有用户对linux内核的强烈感觉,故而linux引入了目录项dentry,目录项使得inode可以安全的停留在内核内存中不被轻易释放掉,一个目录项唯一对应一个由ext3_lookup()函数组建到内核内存的全功能inode索引节点,而一个全功能inode索引节点可以被若干个目录项对应,这也就使得应用更加灵活,目录项通过hash算法,将成千上万的哥们儿目录项们,打散到各个hash短链中【对于hash短链的理解可以参看《其实hash哈希原理很简单 》文章地址 http://gliethttp.cublog.cn】hash短链的引入让文件查询的速度也就被成百上千倍的得到优化提升放大,迅速的找到了一个dentry也就找到了文件夹或文件对应的inode,也就迅速的找到了那个相应的文件夹或文件,也就节省了大家不少的时间.
综述:一个ext3文件系统硬盘上的硬inode索引节点片段信息,唯一的对应物理文件,这是内核内存中全功能inode索引节点存在的唯一硬件文件来源,硬inode索引节点片段信息存储在硬盘上,而全功能inode索引节点和目录项dentry都只是在内核内存中被临时组建起来,随着内核的运行,可能会被释放掉的硬盘上的文件在内核内存中的一个快速索引而已,至于file文件对象,也是一个纯内存对象,和硬盘文件无关,当然file对象和硬盘文件存在着的那点关系由file->f_op=inode->f_op文件对象操作集来勉强维系。