在Unix系统中如何处理文件描述符

6
每个进程都有一个文件描述符表(FDT),每个文件都有一个文件描述符。stdin,stdout和stderr的文件描述符分别为0,1和2。这些值对于所有进程都相同。我认为FDT包含对这些文件的INODE条目的引用。文件描述符在进程之间重复使用,即它们不是全局唯一的。内核是否维护一个全局FDT,以便每个进程的FDT引用?stdin,stdout和stderr的FDT对应什么?这些特殊文件是否与键盘,显示器等链接在一起?
请提供有关该主题的文章、书籍等链接。
1个回答

7
一个好的起点是2001年的文章"通过Linux内核的小径", 虽然实现已经发生了变化,但机制仍然相似,最好在更近期的内核中进行研究。
在内核中,每个打开的文件描述符都对应一个struct file, 它包含有关打开文件或设备的所有信息。文件描述符实际上只是进程的FDT中的索引。在Linux内核中,struct file通过函数fd_install()附加到FDT上。可以通过dup2系统调用struct file重新分配给另一个文件描述符。
如果进程是通过带有CLONE_FILES标志的clone系统调用创建的,则进程可以共享相同的FDT,但没有全局FDT。普通的fork操作会创建一个新的FDT,它是父FDT的副本。这个的实际用途是为多线程应用程序的每个线程创建一个克隆的进程,共享一个公共的FDT,确保所有线程都可以使用相同的整数文件描述符。如果您使用fork/exec创建一个新进程,则新进程将以相同的文件描述符启动,但可以打开和关闭文件而不影响父进程。
stdin、stdout、stderr的FDT条目是从父进程继承而来。这三个FDT条目在内核实现上并没有什么特别之处;它们的含义来源于C库的传统用法。只有父进程可以决定将它们连接到何处,可能连接到字符设备,也可能连接到文件或管道。对于字符设备情况,最常见的是tty或pty设备。免费书籍Linux Device Drivers对此进行了很好的概述

1
在第三段的结尾,我认为你的意思是子进程可以打开和关闭文件,而不会影响父进程。 - Dave Stibrany

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接