UNIX环境编程学习笔记(3)——文件I/O之内核 I/O 数据结构
lienhua34
2014-08-27
内核使用三种数据结构表示打开的文件,分别是文件描述符表、文件表和 V 节点表。
(1) 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。
(2) 内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、添写、同步和非阻塞等)。
(b) 当前文件偏移量。
(c) 指向该文件 V 节点表项的指针。
(3) 每个打开文件(或设备)都有一个 v 节点(v-node)结构。v 节点包含了文件类型和对此文件进行各种操作的函数的指针。v 节点还包含了从磁盘读取的 i 节点(i-node)的信息,i 节点信息包含了文件的所有者、文件长度、文件所在的设备、指向文件的实际数据块在磁盘上的所在位置的指针等。
图 1 显示了一个进程的三张表之间的关系。该进程有两个不同的打开文件,一个文件打开为标准输入(文件描述符为 0),另一个打开为标准输出(文件描述符为 1)。

图 1: 一个进程打开两个文件的内核数据结构
图 2 给出了两个进程打开同一个文件的内核数据结构。假定第一个进程在文件描述符 3 上打开该文件,而另一个进程在文件描述符 4 上打开该文件。打开该文件的每个进程都得到一个文件表项,但对一个给定的文件只有一个 v 节点表项。

图 2: 两个进程打开同一个文件的内核数据结构
了解这些内核数据结构之后,就能够很容易地理解下面的内容,
• 每个进程都有自己的对打开文件的当前偏移量。
• 在完成每个 write 后,在文件表项中的当前文件偏移量即增加所写的字节数。如果这使当前文件偏移量超过了当前文件长度,则在 i 节点表项中的当前文件长度被设置为当前文件偏移量。
• 若一个文件用 lseek 定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为 i 节点表项中的当前文件长度。(这与O_APPEND标志打开文件是不同的。使用 lseek 定位到文件尾端处后,下次调用write 写数据不一定是写在改文件的真正尾端,因为 lseek 和 write 两个不是原子操作,中间可以有另一个进程已使文件长度变长了。)
考虑下面带程序片段,
if (lseek(fd, 0L, SEEK_END) < ) {
printf("lseek error");
}
if (write(fd, buf, ) < ) {
printf("write error");
}
如果是单进程,则上述的程序片段能够正常地将数据添加到文件末尾处。但是,如果是多个进程同时使用此方法将那个数据添加到同一个文件,则会出现问题。假定有两个进程 A 和 B 都对使用上述的程序片段对同一个文件执行添加操作,则其内核数据结构如图 2 所示。假定进程 A 调用了 lseek 将进程 A 的该文件当前偏移量设置为 1000字节(当前文件末尾处)。然后内核切换到进程 B 来执行,进程 B 执行 lseek 也将进程 B 的该文件当前偏移量也设置为 1000 字节(当前文件末尾处),然后进程 B 调用 write 写入 100 字节(此时文件长度变为 1100 字节)。然后,内核切换到进程 A 运行,进程 A 运行 write从其当前文件偏移量(1500 字节)处将数据写到文件中,于是便覆盖了进程 B 所写的数据。
出现该问题的原始的,lseek 定位和 write 写数据是顺序操作,不是一个原子操作,中间会被内核中断。UNIX 提供一个O_APPEND 选项来处理这种情况(见下面说明)。
• 如果用O_APPEND 标志打开了一个文件,则相应标志被设置到文件表项的文件状态标志中。每次对这种具有添写标志的文件执行写操作时,在文件表项中的当前文件偏移量首先被设置成 i 节点表项中的文件长度。这就使得每次写的数据都添加到文件的当前尾端处。
• lseek 函数只修改文件表项中的当前文件偏移量,没有进行任何 I/O操作。
UNIX环境编程学习笔记(3)——文件I/O之内核 I/O 数据结构的更多相关文章
- UNIX环境编程学习笔记(4)——文件I/O之dup复制文件描述符
lienhua342014-08-23 UNIX 提供了两个函数 dup 和 dup2 用于复制一个现存的文件描述符. #include <unistd.h> int dup(int fi ...
- UNIX环境编程学习笔记(2)——文件I/O之不带缓冲的 I/O
lienhua342014-08-25 1 文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用.文件描述符是一个非负整数.当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符. ...
- UNIX环境编程学习笔记(19)——进程管理之fork 函数的深入学习
lienhua342014-10-07 在“进程控制三部曲”中,我们学习到了 fork 是三部曲的第一部,用于创建一个新进程.但是关于 fork 的更深入的一些的东西我们还没有涉及到,例如,fork ...
- UNIX环境编程学习笔记(13)——文件I/O之标准I/O流
lienhua342014-09-29 1 标准 I/O 流 之前学习的都是不带缓冲的 I/O 操作函数,直接针对文件描述符的,每调用一次函数可能都会触发一次系统调用,单次调用可能比较快捷.但是,对于 ...
- UNIX环境编程学习笔记(12)——文件I/O之目录操作
lienhua342014-09-18 1 引言 在 UNIX 系统中,目录是一种特殊的文件类型.我们可以使用 open 函数来打开目录,获取文件描述符,然后调用 stat 函数来获取目录的属性信息, ...
- UNIX环境编程学习笔记(10)——文件I/O之硬链接和符号链接
lienhua342014-09-15 1 文件系统数据结构 UNIX 文件系统通过 i 节点来存储文件的信息.如图 1 所示为一个磁盘柱面上的 i 节点和数据块示意图.其中 i 节点是一个固定长度的 ...
- UNIX环境编程学习笔记(9)——文件I/O之文件访问权限的屏蔽和更改
lienhua342014-09-10 1 文件访问权限 在文件访问权限和进程访问控制中,我们已经讲述过文件访问权限位,为了方便,我们重新列在下面, 表 1: 文件的 9 个访问权限位 st_mod ...
- UNIX环境编程学习笔记(7)——文件I/O之文件访问权限与进程访问控制
lienhua342014-09-02 1 文件的设置用户 ID位 和设置组 ID位 与进程相关联的 ID 如下表所示, 表 1: 与进程相关联的用户 ID 和组 ID 实际用户 ID 我们实际上是谁 ...
- UNIX环境编程学习笔记(6)——文件I/O之判断文件类型
lienhua342014-09-01 1 文件类型 我们平时最常接触的文件类型有普通文件(regular file)和目录(di-rectory file),但是 UNIX 系统提供了多种文件类型: ...
随机推荐
- Android 两级菜单栏
这里来记录下,android 的两级菜单栏,就是顶部切换,和底部的切换.因为在这个上面整了太久的时间,所以特此记录下. 第一种: 先介绍一个网上别人写出来的效果吧,这个当时积分真的很高..CSDN30 ...
- [phy]在uboot阶段失能phy芯片
在uboot阶段power down掉phy芯片 uenvcmd=mdio 0x800; mmc rescan mdio为uboot支持命令 7:phy芯片地址 0:phy芯片工作模式寄存器地址 0x ...
- Face Alignment by Coarse-to-Fine Shape Searching--解析
人脸关键点定位.Face Alignment by Coarse-to-Fine Shape Searching 算法源码详解(上) http://blog.csdn.net/shenxiaolu19 ...
- 基于机器学习人脸识别face recognition具体的算法和原理
引自:http://blog.csdn.net/eclipsesy/article/details/78388468?utm_source=debugrun&utm_medium=referr ...
- 安全运维之:网络实时流量监测工具iftop
网络管理是基础运维中一个很重要的工作,在看似平静的网络运行中,其实暗流汹涌,要保证业务系统稳定运行,网络运维者必须要了解网络的流量状态.各个网段的使用情形,带宽的利用率.网络是否存在瓶颈等,同时,当网 ...
- spring+dubbo整合
创建公共接口或者project用到的一些bean.我这里就仅仅是创建了一个接口.project文件夹例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...
- mha切换脚本可用的
#!/usr/bin/env perl use strict; use warnings FATAL => 'all'; use Getopt::Long; my ( $command, $ss ...
- Qt中与文件目录相关操作
一.与文件目录操作有关操作. Qt中与文件目录相关的操作在QDir中,需加入#include <QDir>语句. QDir::drives()是列出电脑根目录下的所有目录,返回的是QFil ...
- 自然语言交流系统 phxnet团队 创新实训 项目博客 (十二)
关于情感词典的学习总结: 情感倾向可认为是主体对某一客体主观存在的内心喜恶,内在评价的一种倾向.它由两个方面来衡量:一个情感倾向方向,一个是情感倾向度. 情感倾向方向也称为情感极性.在微博中,可以理解 ...
- 《FPGA全程进阶---实战演练》第一章之如何学习FPGA
对于很多初学者,大部分都是急于求成,熟不知越是急于求成,最终越是学无所成,到头来两手空空,要学好FPGA,必须弄懂FPGA本质的一些内容. 1.FPGA内部结构及基本原理 FPGA是可以编程的,必须通 ...