在Linux通用I/O模型中,I/O
操做系列函数(系统调用)都是围绕一个叫作文件描述符的整数展开。这不由让人产生疑问:这个整数表明什么?一个数值表明一个文件吗?随便传一个整数进去调用能够吗?html
原文地址: https://learn-linux.readthedocs.io 。玩转Linux旧群已满,请加新群:278378501 。node
欢迎关注咱们的公众号:小菜学编程 (coding-fan)linux
解答以上疑问,须要更深刻学习——文件描述符(File Descriptor)。shell
理解具体状况,须要了解由内核维护的3个数据结构:编程
这3个数据结构之间的关系以下图所示:微信
内核为每一个进程维护一个文件描述符表,该表每一条目都记录了单个文件描述符的相关信息,包括:数据结构
close-on-exec
内核对全部打开的文件维护一个系统级别的打开文件描述表(open file description table),简称打开文件表。表中条目称为打开文件描述体(open file description),存储了与一个打开文件相关的所有信息,包括:函数
read()
和write()
更新,调用lseek()
直接修改open()
调用设置,例如:只读、只写或读写等i-node
对象指针每一个文件系统会为存储于其上的全部文件(包括目录)维护一个i-node
表,单个i-node
包含如下信息:学习
FIFO
i-node
存储在磁盘设备上,内核在内存中维护了一个副本,这里的i-node
表为后者。副本除了原有信息,还包括:引用计数(从打开文件描述体)、所在设备号以及一些临时属性,例如文件锁。spa
上图中,详细描述了两个进程诸多文件描述符,以及相互关系。
在进程A
中,文件描述符1和文件描述符20都指向同一个打开文件描述体(标号23)。这极可能是经过调用dup()
系列函数造成的。
文件描述符复制,在某些场景下很是有用,好比:标准输入/输出重定向。在shell
下,完成这个操做很是简单,大部分人都会,可是极少人思考过背后的原理。
大概描述一下须要的几个步骤,以标准输出(文件描述符为1)重定向为例:
dup
将文件描述符n复制到1;进程A
的文件描述符2和进程B
的文件描述符2都指向同一个打开文件描述体(标号73)。这种情形极可能发生在调用fork()
派生子进程以后,好比A
调用fork()
派生出B
。这时,B
做为子进程,从父进程A
继承了文件描述符表,其中包括图中标明的文件描述符2。这就是子进程继承父进程打开的文件
这句话的由来。
固然了,进程A
经过Unix
套接字将一个文件描述符传递给B
也会出现相似的情形,但通常文件描述符数值是不同的。同时为2要很是凑巧才发生。
更多文章请访问:学习Linux
订阅更新,获取更多学习资料,请关注咱们的 微信公众号 :