【问题标题】:Redirecting stdout to stdin in POSIX C在 POSIX C 中将标准输出重定向到标准输入
【发布时间】:2018-01-15 10:21:50
【问题描述】:

我正在尝试编写一个将stdout 重定向到stdin 的程序,主要是为了更好地了解dup2() 的工作原理。我尝试编写一个简单的程序,这样如果你 printf() 某事,你可以稍后 scanf() 它回来,但没有设法让它工作。首先我尝试只使用dup2(0, 1),认为它会将stdout (1) 重定向到stdin (0)。这没有用。我认为由于一个用于输入,另一个用于输出,它们可能不兼容,所以我尝试使用管道来执行此操作,如下所示:

#include <stdio.h>
#include <unistd.h>
int main() {
    int pipe_desc[2];
    pipe(pipe_desc);
    dup2(pipe_desc[0], 0);
    dup2(pipe_desc[1], 1);
    printf("foo");
    char bar[20];
    scanf("%s", bar);
    fprintf(stderr, "%s", bar);
}

然而,现在即使printf,据我所知,应该将"foo" 放入管道,当我调用scanf 时,程序只是挂在那里,既不从标准输入读取,也不从管道。怎么了?这段代码到底发生了什么?这种重定向可以在没有管道(或任何其他辅助结构)的情况下完成吗?

【问题讨论】:

  • 您似乎忘记了输出到stdout 默认情况下是行缓冲。要么明确地fflush 缓冲区,要么在你打印的字符串中添加一个尾随换行符。
  • scanf 读取 空格分隔的字符串。 stdin 是 缓冲的 ...也许是这 2 个。试试写printf("foo\n");
  • @Someprogrammerdude 行在连接到终端时缓冲。在这里,甚至可能完全...
  • @AnttiHaapala 可能是真的。但是我想说这取决于 stdio 系统的懒惰程度,是否在程序启动时打开文件并设置缓冲,或者何时完成第一个输出操作。
  • 我认为它通常不会在第一次操作之前设置,因为setvbuf

标签: c io posix


【解决方案1】:

你的工作原理,代码中有解释。

#include <stdio.h>
#include <unistd.h>
int main() {
        int pipe_desc[2];
        pipe(pipe_desc);
        printf("pid = %d \n",getpid());
        /* above statement creates 2 descriptors 3 & 4. 3 is for read and 4 is for write**/
        dup2(pipe_desc[0], 0);
        /** 3 is duplicates with 0(stdin) i.e if you try to do scanf, it won't scan from keyboard, it will scan from pipe(read end, for that make sure something should be there in pipe  **/
        dup2(pipe_desc[1], 1);
        /** 4 is duplicates with 1 (stdout) i.e if you try to write onto screen, it won't. It will try into pipe write end **/
        /** SO TILL NOW FD DETAILS
                0,3 --> PIPE_DESC[0]
                1,4 --> PIPE_DESC[1] 
        **/
        #if 1
        fflush(stdout);
        printf("foo\n");//it won't print 
        char bar[20];
        scanf("%s", bar);//it won't scan bcz 0 is poiting to pipe_desc[0]
        #endif
        /** YOU CAN CHECK USING OTHER TERMINAL "ls -l /proc/pid/fd/" **/

        fprintf(stderr, "%s", bar);// fd 2 is still available.So foo gets printed on screen
}

在上述程序运行时打开另一个终端,使用查看 fd 详细信息

root@xyz-PC:/home/achal/s_flow/cpp# ls -l /proc/4503/fd
total 0
lr-x------ 1 root root 64 Jan 15 16:45 0 -> pipe:[782489]
l-wx------ 1 root root 64 Jan 15 16:45 1 -> pipe:[782489]
lrwx------ 1 root root 64 Jan 15 16:45 2 -> /dev/pts/9
lr-x------ 1 root root 64 Jan 15 16:45 3 -> pipe:[782489]
l-wx------ 1 root root 64 Jan 15 16:45 4 -> pipe:[782489]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多