是否有可能linux文件描述符0 1 2不适用于stdin,stdout和stderr?

时间:2014-03-13 02:28:47

标签: linux sockets kernel

程序开始时,默认情况下是否需要stdin,stdout和stderr的文件描述符0,1和2? API调用(例如open(...),socket(...))是否会返回0,1和2,因为这些值已经被采用了?是否存在open(...)或socket(...)返回0,1或2的情况.0,1和2与stdin,stdout和stderr无关。

3 个答案:

答案 0 :(得分:12)

file descriptor级别, stdin 被定义为文件描述符0 stdout 被定义为文件描述符1 ;并且 stderr 被定义为文件描述符2 。请参阅this

即使您的程序 - 或shell-更改(例如,使用dup2(2)重定向)什么是文件描述符0,它始终保持 stdin (因为根据定义STDIN_FILENO是0)。

当然, stdin 可以是管道,套接字或文件(​​不是终端)。您可以使用isatty(3)进行测试,如果它是tty,和/或使用fstat(2)获取状态信息。

open(2)pipe(2)socket(2)等Syscall可能会提供例如STDIN_FILENO(即0)如果该文件描述符是空闲的(例如因为它之前是close(2) - d)。但是当发生这种情况时,根据定义,它仍然是 stdin

当然,在stdio(3)中,FILEstdin有点复杂。您的计划可以fclose(3)freopen(3)fdopen(3) ...

当神奇地启动/sbin/init时,内核可能会将 stdin stdout stderr 文件描述符设置到控制台作为第一个过程。

答案 1 :(得分:3)

  1.   

    程序开始时,默认情况下是否为stdin,stdout和stderr采用文件描述符0 1 2。

    如果您通常在交互式shell中启动程序,是的。

    通过@EJP:

      

    如果程序是由inetd启动的,或者其他任何行为相同的方式,也会将套接字继承为FD 0。

  2.   

    开放(...),套接字(...)之类的API不会返回0 1 2,因为已经采用了这些值。

  3.   

    是否有任何情况,open(...)或socket(...)将返回0 1 2。

    是的,如果您执行类似

    的操作
    close(0);
    close(1);
    close(2);
    open(...); /* this open will return 0 if success */
    

答案 2 :(得分:2)

尽管已经有一些答案,但是我发现它们的信息不足以解释完整的故事。

自从我继续研究之后,我正在添加自己的发现。

每当进程启动时,正在运行的进程的条目都会添加到/proc/<pid>目录中。在此保留与流程相关的所有数据。同样,在进程启动时,内核会为进程分配3个文件描述符,以便与称为stdinstdoutstderr的3个数据流进行通信。
linux内核使用一种算法来始终创建具有最小可能整数值的FD,因此这些数据流被映射为数字012

由于这些仅是对流的引用,因此我们可以关闭流。在我们的情况下,close(<fd>)可以轻松调用close(1)来关闭文件描述符。

在进行ls -l /proc/<pid>/fd/时,我们仅在02上列出两个FD。
如果现在执行一次open()调用,内核将创建一个新的FD来映射此新文件引用,并且由于内核使用最低的整数优先算法,因此它将选择整数值1

现在,创建的新FD指向我们打开的文件(使用open() syscall)
现在发生的任何数据传输,不是通过先前链接的默认数据流,而是通过我们打开的新文件。

是的,我们可以将FD 012映射到任何文件,而不必将stdinstdout或{{ 1}}