文件描述符和打开的文件之间似乎是一一对应的关系,但实际可以多个文件描述符指向同一打开文件,这些文件描述符可能在相同或不同的进程中打开。内核维护的三个数据结构:
(1) 进程级的文件描述符表
(2) 系统级的打开文件表
(3) 文件系统的i-node表
1.进程级的文件描述符表
针对每个进程,内核为其维护打开文件的描述符表,该表的每一条目都记录了单个文件描述符的相关信息:
(a) 控制文件描述符操作的一组标志
(b) 对打开文件句柄的引用
2.系统级的打开文件表
内核对所有打开的文件维护有一个系统级的描述表(也称为,打开文件表),并将表中各条目称为打开文件句柄。一个打开文件句柄存储了与一个打开文件相关的全部信息:
(a) 当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)
(b) 打开文件时所使用的状态标志(即,open()的flags参数)
(c) 文件的访问模式(如调用open()时所设置的只读模式、只写模式、或读写模式)
(d) 与信号驱动I/O相关的设置
(e) 对该文件i-node对象的引用
3.文件系统的i-node表
每个文件系统都会为驻留其上的所有文件建立一个i-node表,包含如下信息:
(a) 文件类型(例如,常规文件、套接字、或FIFO)和访问权限
(b) 一个指针,指向该文件所持有的锁的列表
(c) 文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳
下图展示了文件描述符表、打开的文件句柄,以及i-node之间的关系
一些结论:
(1) 两个不同的文件描述符,若指向同一打开的文件句柄,将共享同一文件偏移量。因此,如果通过其中一个文件描述符来修改文件偏移量(由read()、write()或lseek()所致),那么从另一个文件描述符中也会观察到这一变化。无论这两个文件描述符分属于不同进程,还是同属于一个进程,情况都是如此。
(2) 要获取和修改打开的文件标志(例如,O_APPEND、O_NONBLOCK、O_ASYNC),可执行fcntl()的F_GETFL和F_SETFL操作。
(3) 文件描述符标志(即,close-on-exec)为进程和描述符所私有,对这一标志的修改不会影响同一进程或不同进程中其他文件描述符。
提高linux对最大进程数和最大打开文件描述符数的限制:http://www.linuxdiyf.com/linux/15700.html
Linux最大打开文件描述符数:http://www.linuxdiyf.com/linux/14776.html
Linux系统文件描述符理解:http://www.linuxdiyf.com/linux/13896.html
Linux下如何修改文件描述符的大小:http://www.linuxdiyf.com/linux/9893.html
Linux下文件描述符:http://www.linuxdiyf.com/linux/2286.html