内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另外一个进程可能产生的影响。数据结构
1>每一个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,可将其视为一个矢量,每一个描述项占用一项。与每一个文件描述符相关联的是:函数
注:其中close-on-exec标志,若是某个文件符设置了该标志,fcntl(fd, F_SETFD, 1), 则在该进程调用exec函数以前为exec族函数关闭对应的文件描述符。spa
2>内核为全部打开文件维持一张文件表项。每一个文件表项包含:指针
注:在文件表或者v索引节点中都有索引计数,引用计数为0的时候,文件引用为0的时候就能够收回此表项blog
fork后父子进程各自的每个打开的文件描述符共享同一个文件表项索引
3>每一个打开文件(或设备)都有个v节点结构。v节点包含了文件类型和对此文件进行各类操做的函数指针。 对于大多数文件,v节点还包含了该文件的i节点(索引节点)。这些信息是在打开文件时从磁盘上读入内存的,因此全部关于文件的信息都是快速可供使用的。进程
例如:i节点包含了文件的全部者、文件长度、文件所在设备、只想文件实际数据块在磁盘上所在位置的指针等等。内存
注:Linux没有使用v节点,而是使用了通用的i节点结构。虽然这两种实现有所不一样,但在概念上,v节点和i节点是同样的。二者都指向文件系统所特有的i节点结构。同步
两个独立进程各自打开同一个文件(下图),此图中能够看出,对于同一个文件,打开该文件的每一个进程都获得一个文件表项,但对一个给定的文件只有一个v节点表项。而每一个进程都有本身的文件表项的一个理由是:使每一个进程都有它本身的对该文件的当前偏移量。it
dup后的文件表项
原子操做:
由踱步组成的一个操做,若是该操做原子地执行,要么执行完全部的步骤,要么一步也不执行,不可能只执行全部步骤的一个子集。