UNIX内核用于所有I/O的数据结构
2015-01-05 16:29
225 查看
内核使用三种数据结构表示打开的文件,分别是文件描述符表、文件表和 V 节点表。它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。
内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、添写、同步和非阻塞等)。
(b) 当前文件偏移量。
(c) 指向该文件 V 节点表项的指针。
每个打开文件(或设备)都有一个 v 节点(v-node)结构。v 节点包含了文件类型和对此文件进行各种操作的函数的指针。v 节点还包含了从磁盘读取的 i 节点(i-node)的信息,i 节点信息包含了文件的所有者、文件长度、文件所在的设备、指向文件的实际数据块在磁盘上的所在位置的指针等。
图 1 显示了一个进程的三张表之间的关系。该进程有两个不同的打开文件,一个文件打开为标准输入(文件描述符为 0),另一个打开为标准输出(文件描述符为 1)。
![](http://img.blog.csdn.net/20150105163336468)
图 1: 一个进程打开两个文件的内核数据结构
图 2 给出了两个进程打开同一个文件的内核数据结构。假定第一个进程在文件描述符 3 上打开该文件,而另一个进程在文件描述符 4 上打开该文件。打开该文件的每个进程都得到一个文件表项,但对一个给定的文件只有一个 v 节点表项。
![](http://img.blog.csdn.net/20150105163415280)
图 2: 两个进程打开同一个文件的内核数据结构
有了这些数据结构,对一些概念和操作有以下说明:
每个进程都会获得自己的文件表项,因此,每个进程都有它自己的对该文件的当前偏移量。
在完成每个 write 后,在文件表项中的当前文件偏移量即增加所写入的字节数。如果这导致当前文件偏移量超出了当前文件长度,则将 i 节点表项中的当前文件长度设置为当前文件偏移量(也就是该文件加长了)。
如果用O_APPEND 标志打开一个文件,则相应标志也被设置到文件表项的文件状态标志中。每次对这种具有追加写标志的文件执行写操作时,文件表项中的当前文件偏移量首先会被设置为 i 节点表项中的文件长度。这就使得每次写入的数据都追加到文件的当前尾端处。
若一个文件用 lseek 定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为 i 节点表项中的当前文件长度。可知,这与上述用O_APPEND 标志打开文件的方式是不同的。
lseek 函数只修改文件表项中的当前文件偏移量,不进行任何的 I/O 操作。
每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。
内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、添写、同步和非阻塞等)。
(b) 当前文件偏移量。
(c) 指向该文件 V 节点表项的指针。
每个打开文件(或设备)都有一个 v 节点(v-node)结构。v 节点包含了文件类型和对此文件进行各种操作的函数的指针。v 节点还包含了从磁盘读取的 i 节点(i-node)的信息,i 节点信息包含了文件的所有者、文件长度、文件所在的设备、指向文件的实际数据块在磁盘上的所在位置的指针等。
图 1 显示了一个进程的三张表之间的关系。该进程有两个不同的打开文件,一个文件打开为标准输入(文件描述符为 0),另一个打开为标准输出(文件描述符为 1)。
图 1: 一个进程打开两个文件的内核数据结构
图 2 给出了两个进程打开同一个文件的内核数据结构。假定第一个进程在文件描述符 3 上打开该文件,而另一个进程在文件描述符 4 上打开该文件。打开该文件的每个进程都得到一个文件表项,但对一个给定的文件只有一个 v 节点表项。
图 2: 两个进程打开同一个文件的内核数据结构
有了这些数据结构,对一些概念和操作有以下说明:
每个进程都会获得自己的文件表项,因此,每个进程都有它自己的对该文件的当前偏移量。
在完成每个 write 后,在文件表项中的当前文件偏移量即增加所写入的字节数。如果这导致当前文件偏移量超出了当前文件长度,则将 i 节点表项中的当前文件长度设置为当前文件偏移量(也就是该文件加长了)。
如果用O_APPEND 标志打开一个文件,则相应标志也被设置到文件表项的文件状态标志中。每次对这种具有追加写标志的文件执行写操作时,文件表项中的当前文件偏移量首先会被设置为 i 节点表项中的文件长度。这就使得每次写入的数据都追加到文件的当前尾端处。
若一个文件用 lseek 定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为 i 节点表项中的当前文件长度。可知,这与上述用O_APPEND 标志打开文件的方式是不同的。
lseek 函数只修改文件表项中的当前文件偏移量,不进行任何的 I/O 操作。
相关文章推荐
- Linux 内核用于I/O的三个数据结构
- UNIX内核的文件数据结构 -- v 节点与 i 节点
- 内核用于I/O的数据结构
- 数据结构:有人设计以下算法用于删除整数顺序表L中所有值在[x,y]范围内的元素,该算法显然不是高效的,请设计一个同样功能的高效算法。
- 用于查询当前数据库中所有表格的记录条数
- Unix/Linux环境C编程入门教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建
- 一个Unix内核级别漏洞(一)
- 设计相应的数据结构和算法,尽量高效的统计一片英文文章(总单词数目)里出现的所有英文单词, * 按照在文章中首次出现的顺序打印输出该单词和它的出现次数。
- 在Delhpi中得到本地IP地址,并计算出本网段的所有IP地址(可用于广播)
- UNIX内核(5):内核开发的特点
- Linux内核数据结构—链表
- elasticsearch核心知识---48.内核级知识点:深入type底层数据结构
- [Linux] 内核模块&proc使用 实例:统计所有进程的信息
- [笔记]《Linux内核设计与实现》第六章内核数据结构
- 数据结构总结(用于个人学习)
- 用于查询当前数据库中所有表格的记录条数的脚本
- 设计一个模块,功能是列出系统中所有内核线程的程序名、PID号和进程状态。
- [mahout in action]mahout中用于推荐引擎的数据结构(二)
- 算法导论笔记:21用于不相交集合的数据结构
- 用于并行计算的多线程数据结构,第 1 部分: 设计并发数据结构