标准流 stdin 和 stdout 在哪里创建?

问题描述 投票:0回答:5

在 ANSI C 中,我们说输入由 (s/v/f)scanf 获取并存储在

stdin
中,当谈论输出时,我们会说
stdout
。不过我想知道它们在 Linux (Unix) 中的位置。它们驻留在特定文件夹下吗?或者它们(
stdin
/
stdout
)是任意的(也就是说,不存在这样的东西)?

c stdout stdin
5个回答
7
投票

它们是操作系统为您的进程创建的流。没有与它们关联的命名文件对象,因此它们在文件系统中没有表示,尽管正如 unwind 指出的那样,如果您的 UNIX 变体支持这样的东西,则可以通过伪文件系统访问它们。


5
投票

stdin
是一个
FILE *
,指的是与文件描述符
0
相关联的 stdio(标准 io)结构。文件描述符是类 Unix 系统(例如 Linux)用来与应用程序讨论特定的类似文件的事物的东西。 (事实上,我很确定 Windows 也能做到这一点)。

文件描述符

0
可以指任何类型的 file,但为了有意义,它必须是可以调用
read
的文件描述符(它必须是常规文件、steam 套接字或为其打开的字符设备)读取或管道的读取端,而不是目录文件、数据报套接字或块设备)。

类 Unix 系统中的进程从类 Unix 系统中的父进程继承其打开文件描述符。因此,要运行一个将标准输入设置为父级标准输入之外的程序,您可以这样做:

 int new_stdin = open("new_stdin_file, O_RDONLY);
 pid_t fk = fork();
 if (!fk) { // in the child
     dup2(new_stdin, 0);
     close(new_stdin);
     execl("program_name", "program_name", NULL);
     _exit(127); // should not have gotten here, and calling exit (without _ ) can have
                 // side effects because it runs atexit registered functions, and we
                 // don't want that here
 } else if (fk < 0) {
      // in parent with error from fork
 } else {
     // in parent with no error so fk = pid of child
 }
 close(new_stdin); // we don't need this anymore

dup2
将第一个文件描述符参数复制为第二个(如果当前进程打开了第二个文件描述符参数,则在执行此操作之前关闭第二个文件描述符参数)。

fork
创建当前进程的副本。
execl
exec
函数系列之一,它使用
execve
系统调用将当前程序替换为另一个程序。
fork
exec
的组合是程序通常运行的方式(即使隐藏在其他函数中)。

在上面的示例中,我们可以运行新程序,并将 stdin 设置为管道、tty(串行端口/TeleTYpe)或其他几个东西的读取端。其中一些在文件系统中具有名称,而另一些则没有(例如某些管道和套接字,尽管有些在文件系统中确实有名称)。

Linux 使

/proc/self/fd/0
成为指向当前进程中以
0
打开的文件的符号链接。
/proc/%i/fd/0
pid
将使用
printf
语法表示任意 pid(进程 ID)到同一事物的符号链接。这些符号链接通常可用于在文件系统中查找真实文件(使用 readlink 系统调用),但如果文件实际上不存在于文件系统中,则链接数据(通常是文件名)只是一个字符串这告诉了一些关于该文件的信息。

我应该在这里指出,stdin (fd 0) 引用的文件,即使它位于文件系统中,也可能不只有一个名称。它可能有多个硬链接,因此它也有多个名称——每一个名称都与任何其他硬链接的名称一样。此外,如果自打开以来它的所有硬链接都是

unlinked
,那么它可能根本没有名称,尽管它的数据仍然存在于磁盘上,直到它的所有打开的文件描述符都被关闭。

如果您实际上不需要知道它在文件系统中的位置,而只是想要一些有关它的数据,您可以使用

fstat
系统调用。这就像
stat
系统调用和命令行实用程序,但已打开的文件除外。

我在这里所说的关于

stdin
(fd 0) 的所有内容都应该适用于 stdout (fd 1) 和 stderr (fd 2),只不过它们都是可写的而不是可读的。

如果您想了解有关我提到的任何功能的更多信息,请务必通过键入以下内容在手册页中查找它们:

man fork

在命令行上。我提到的大多数函数都在手册页的第 2 部分中,但一两个可能在第 1 部分中,因此

man 2 fork
也可以工作,并且当命令行工具与函数具有相同名称时可能很有用。


2
投票

在Linux中,一般可以通过

stdin
中的/proc文件系统找到
/proc/self/fd/0
,stdout为
/proc/self/fd/1


1
投票

stdin
是标准输入 - 例如键盘输入。
stdout
是标准输出 - 例如,监视器。

欲了解更多信息,请阅读


0
投票

如果你跑步:

./myprog < /etc/passwd

那么

stdin
在文件系统中作为
/etc/passwd
存在。如果你只是跑步

./myprog

在终端上交互,然后

stdin
存在于文件系统中,无论您的终端设备是什么(可能是
/dev/pts/5
或其他设备)。

如果你跑步

cat /etc/passwd | ./myprog

那么

stdin
是一个匿名管道,在文件系统中没有实例化,但是 Linux 允许您通过
/proc/12345/fd/0
获取它,其中
12345
myprog
的 pid。

© www.soinside.com 2019 - 2024. All rights reserved.