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

发布于 2024-10-07 21:50:35 字数 202 浏览 4 评论 0原文

在 ANSI C 中,我们说输入由 (s/v/f)scanf 获取并存储在 stdin 中,在谈论输出时我们说 stdout 。不过我想知道它们在 Linux (Unix) 中的位置。它们驻留在特定文件夹下吗?或者它们(stdin/stdout)是任意的(也就是说,不存在这样的东西)?

In ANSI C, we say input is taken by (s/v/f)scanf and stored in stdin, we say something for stdout when talking about output. However I wonder where they reside in Linux (Unix). Do they reside under a specific folder? Or are they (stdin/stdout) arbitrary (that is, no such things exist)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

对你而言 2024-10-14 21:50:35

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

They are streams created for your process by the operating system. There is no named file object associated with them, and so they do not have a representation within the file system, although as unwind points out, they may be accessed via a pseudo file system if your UNIX variant supports such a thing.

温柔戏命师 2024-10-14 21:50:35

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

文件描述符 0 可以引用任何类型的文件,但为了有意义,它必须是可以调用 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 创建当前进程的副本。 execlexec 系列函数之一,它使用 execve 系统调用将当前程序替换为另一个程序。 forkexec 的组合是程序通常的运行方式(即使隐藏在其他函数中)。

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

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

我应该在这里指出,stdin (fd 0) 引用的文件,即使它位于文件系统中,也可能不只有一个名称。它可能有多个硬链接,因此它也有多个名称——每一个名称都与任何其他硬链接一样多。此外,如果自打开以来它的所有硬链接都已取消链接,则它可能根本没有名称,尽管它的数据仍然存在于磁盘上,直到它的所有打开的文件描述符都被关闭。

如果您实际上不需要知道它在文件系统中的位置,而只是想要一些有关它的数据,您可以使用 fstat 系统调用。这类似于 stat 系统调用和命令行实用程序,但已打开的文件除外。

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

键入:在手册页中查找它们

man fork

如果您想了解有关我提到的任何函数的更多信息,请务必通过在命令行上 。我提到的大多数函数都在手册页的第 2 部分中,但一两个可能在第 1 部分中,因此 man 2 fork 也可以工作,并且当命令行工具具有相同的功能时可能会很有用名称作为函数。

stdin is a FILE * referring to the stdio (standard io) structure that is tied to the file descriptor 0. File descriptors are what Unix-like systems, such as Linux, use to talk with applications about particular file-like things. (Actually, I'm pretty sure that Windows does this as well).

File descriptor 0 may refer to any type of file, but to make sense it must be one that read can be called on (it must be a regular file, a steam socket, or a character device opened for reading or the read side of a pipe, as opposed to a directory file, data gram socket, or a block device).

Processes in Unix-like systems inherit their open file descriptors from their parent process in Unix-like systems. So to run a program with stdin set to something besides the parent's stdin you would do:

 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 duplicates the first file descriptor argument as the second (closing the second before doing so if it were open for the current process).

fork creates a duplicate of the current process. execl is one of the exec family of functions, which use the execve system call to replace the current program with another program. The combination of fork and exec are how programs are generally run (even when hidden within other functions).

In the above example we could have run the new program with stdin set to the read end of a pipe, a tty (serial port / TeleTYpe), or several other things. Some of these have names present in the filesystem and others do not (like some pipes and sockets, though some do have names in the filesystem).

Linux makes /proc/self/fd/0 a symbolic link to the file opened as 0 in the current process. /proc/%i/fd/0, pid would represent the symbolic link to the same thing for an arbitrary pid (process ID) using the printf syntax. These symbolic links are often usable to find the real file in the filesystem (using the readlink system call), but if the file does not actually exist in the filesystem the link data (what would usually be a file name) instead is just a string that tells a little bit about the file.

I should point out here that a file that stdin (fd 0) refers to, even if it is in the filesystem, may not have just one name. It may have more than one hard link, so it would have more than one name -- and each of these would be just as much its name as any other hard link. Additionally it may have no name at all if all of its hard links have been unlinked since it was opened, though it's data would still live on the disk until all open file descriptors for it are closed.

If you don't actually need to know where it is in the filesystem, but just want some data about it you can use the fstat system call. This is like the stat system call and command line utility, except for already open files.

Everything I said here about stdin (fd 0) should be applicable to stdout (fd 1) and stderr (fd 2) except that they will both be writable rather than readable.

If you want to know more about any of the functions I mentioned be sure to look them up in the man pages by typing:

man fork

on the command line. Most functions I mentioned are in section 2 of the man pages, but one or two may be in section one, so man 2 fork will work too, and may be useful when a command line tool has the same name as a function.

初见终念 2024-10-14 21:50:35

在 Linux 中,您通常可以通过 /proc 文件系统找到 stdin/proc/self/fd/0 中,标准输出为 /proc/self/fd/1

In Linux, you can generally find stdin through the /proc file system in /proc/self/fd/0, and stdout is /proc/self/fd/1.

站稳脚跟 2024-10-14 21:50:35

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

如需了解更多信息,请阅读

stdin is standard input - for example, keyboard input.
stdout is standard output - for example, monitor.

For more info, read this.

離人涙 2024-10-14 21:50:35

如果运行:

./myprog < /etc/passwd

stdin 在文件系统中以 /etc/passwd 形式存在。如果您只是

./myprog

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

如果您运行,

cat /etc/passwd | ./myprog

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

If you run:

./myprog < /etc/passwd

then stdin exists in the filesystem as /etc/passwd. If you just run

./myprog

interactively on a terminal, then stdin exists in the filesystem as whatever your terminal device is (probably /dev/pts/5 or something).

If you run

cat /etc/passwd | ./myprog

then stdin is an anonymous pipe and has no instantiation in the filesystem, but Linux allows you to get at it via /proc/12345/fd/0 where 12345 is the pid of myprog.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文