写入 stdin 并从 stdout 读取(UNIX/LINUX/C 编程)

发布于 2024-12-04 05:41:17 字数 466 浏览 1 评论 0原文

我正在做一个作业,其中一个程序将文件描述符作为参数(通常来自 exec 调用中的父级)并从文件中读取并写入文件描述符,在我的测试中,我意识到该程序可以工作从命令行,如果我使用 0、1 或 2 作为文件描述符,则不会给出错误。这对我来说很有意义,除了我可以写入标准输入并将其显示在屏幕上。

对此有解释吗?我一直认为 stdin/stdout 上有一些保护,并且您当然不能 fprintf 到 stdin 或从 stdout 进行 fgets。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    char message[20];
    read(STDOUT_FILENO, message, 20);
    write(STDIN_FILENO, message, 20);

    return 0;
}

I was working on an assignment where a program took a file descriptor as an argument (generally from the parent in an exec call) and read from a file and wrote to a file descriptor, and in my testing, I realized that the program would work from the command-line and not give an error if I used 0, 1 or 2 as the file descriptor. That made sense to me except that I could write to stdin and have it show on the screen.

Is there an explanation for this? I always thought there was some protection on stdin/stdout and you certainly can't fprintf to stdin or fgets from stdout.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    char message[20];
    read(STDOUT_FILENO, message, 20);
    write(STDIN_FILENO, message, 20);

    return 0;
}

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

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

发布评论

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

评论(5

弱骨蛰伏 2024-12-11 05:41:17

尝试写入标记为只读的文件(反之亦然)将导致 writeread 返回 -1,并失败。在这种特定情况下,stdin 和 stdout 实际上是同一个文件。本质上,在程序执行之前(如果不进行任何重定向),shell 会执行以下操作:

  if(!fork()){
       <close all fd's>
       int fd = open("/dev/tty1", O_RDWR);
       dup(fd);
       dup(fd);
       execvp("name", argv);
  }

因此,stdin、out 和 err 都是同一文件描述符的重复项,打开以供读取和写入。

Attempting to write on a file marked readonly or vice-versa would cause write and read to return -1, and fail. In this specific case, stdin and stdout are actually the same file. In essence, before your program executes (if you don't do any redirection) the shell goes:

  if(!fork()){
       <close all fd's>
       int fd = open("/dev/tty1", O_RDWR);
       dup(fd);
       dup(fd);
       execvp("name", argv);
  }

So, stdin, out, and err are all duplicates of the same file descriptor, opened for reading and writing.

迷途知返 2024-12-11 05:41:17
read(STDIN_FILENO, message, 20); 
write(STDOUT_FILENO, message, 20);

应该有效。注意 - 标准输出可能与标准输入不同(即使在命令行上)。您可以将另一个进程的输出作为标准输入输入到您的进程中,或者将标准输入/标准输出安排为文件。

fprintf/fgets 有一个缓冲区 - 从而减少系统调用的次数。

read(STDIN_FILENO, message, 20); 
write(STDOUT_FILENO, message, 20);

Should work. Note - stdout my be a different place from stdin (even on the command line). You can feed output from another process as stdin into you process, or arrange the stdin/stdout to be files.

fprintf/fgets have a buffer - thus reducing the number of system calls.

唯憾梦倾城 2024-12-11 05:41:17

最佳猜测 - stdin 指向输入的来源,即您的终端,而 stdout 指向输出应该去的地方,即您的终端。因为它们都指向同一个地方,所以它们可以互换(在本例中)?

Best guess - stdin points to where the input is coming from, your terminal and stdout points to where output should be going, your terminal. Since they both point to the same place they are interchangeable(in this case)?

墨小墨 2024-12-11 05:41:17

文件描述符 0、1 和 2 很可能都对读取和写入开放(事实上,它们都引用相同的底层“打开文件描述”),在这种情况下,您正在做的事情将会起作用。但据我所知,没有任何保证,所以它也可能行不通。我确实相信 POSIX 某处指定,当 shell 调用程序时,如果 stderr 连接到终端,它应该是可读可写的,但我无法立即找到参考。

一般来说,我会建议不要这样做从 stdout 或 stderr 读取,除非您正在寻找从中读取密码的终端,并且 stdin 已被重定向(不是 tty)。我建议永远不要写入标准输入 - 这很危险,你最终可能会破坏用户不希望写入的文件!

It's very possible that file descriptors 0, 1, and 2 are all open for both reading and writing (and in fact that they all refer to the same underlying "open file description"), in which case what you're doing will work. But as far as I know, there's no guarantee, so it also might not work. I do believe POSIX somewhere specifies that if stderr is connected to the terminal when a program is invoked by the shell, it's supposed to be readable and writable, but I can't find the reference right off..

Generally, I would recommend against ever reading from stdout or stderr unless you're looking for a terminal to read a password from, and stdin has been redirected (not a tty). And I would recommend never writing to stdin - it's dangerous and you could end up clobbering a file the user did not expect to be written to!

相思碎 2024-12-11 05:41:17

如果您在 UNIX 上运行程序,

myapp < input > output

您可以打开 /proc/{pid}/fd/1 并从中读取,打开 /proc/{pid}/fd/0 并对其进行写入,例如,复制 output< /code> 到输入。 (可能有一种更简单的方法可以做到这一点,但我知道它有效)

如果你用心去做,你可以做任何令人困惑的事情。 ;)

If you run a program on UNIX

myapp < input > output

You can open /proc/{pid}/fd/1 and read from it, open /proc/{pid}/fd/0 and write to it and for example, copy output to input. (There is possibly a simpler way to do this, but I know it works)

You can do any manner of things which are plain confusing if you put your mind to it. ;)

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