【问题标题】:How to use dup2 to redirect stdin and stdout to pipe file descriptors?如何使用 dup2 将标准输入和标准输出重定向到管道文件描述符?
【发布时间】:2020-01-06 07:47:56
【问题描述】:

我试图分叉一个进程并将父级的标准输出重定向到管道的写入端,将子级的标准输入重定向到管道的读取端。孩子应该读取整数,直到父母打印零。父级打印从 1 到 3,然后打印 0。父级和子级都打印开始和结束的时间。由于父母无法打印到标准输出,它会将其开始和结束时间发送给孩子,并且孩子会打印其开始时间和结束时间以及父母开始时间和结束时间。我本可以使用 dup 并将 stdout 重定向到另一个文件描述符,但我选择让它变得简单。该程序非常简单,但我得到的输出没有场景。

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main() 
{ 
    int fd[2];
    int p = pipe(fd);
    int ch = fork();

    if (ch)
    {
        // Parent - Counts from 1 to 3
        int dp = dup2(fd[1], 1);
        printf("Cnt_Started_at_%d\n", time(NULL));
        for (int i = 0; i <= 3; i++)
        {
            printf("Parent %d\n", i);
            sleep(1);
        }
        printf("0\n");
        printf("Cnt_Finished_at_%d\n", time(NULL));
    }
    else 
    {
        // Child - Terminated by 0
        int dp = dup2(fd[0], 0);
        printf("Trm_Started_at_%d\n", time(NULL));
        char buffer[100];
        scanf("%s", buffer);
        printf("%s\n", buffer);

        int i; 
        while (scanf("Parent %d", &i) && i)
            printf("Recieved: %d\n", i);

        scanf("%s", buffer);
        printf("%s\n", buffer);
        printf("Trm_Finished_at_%d\n", time(NULL));
    }
}

输出:

Trm_Started_at_1578295974
Cnt_Started_at_1578295974
Parent
Trm_Finished_at_1578295978

【问题讨论】:

  • 这里的dup有什么用?你想让父母只写,让孩子只读吗?在这种情况下,您可能需要考虑关闭孩子和父母各自的 fd...
  • 是的,这就是我想要的。我考虑过这样做,但我在 dup2 的手册页中读到,如果之前打开了新文件描述符,它首先关闭它,然后分配它。

标签: c pipe fork dup2 dup


【解决方案1】:

根本问题是使用“scanf %s”来读取消息。回想一下,“%s”在遇到空白时会停止读取,并将空白放回缓冲区。

来自父级的初始消息是“Cnt_Started_at_1234\n”。此子进程将读取令牌,但会将尾随的 '\n' 留在缓冲区中。

接下来,父级将发送“父级 0\n”。 Child 将尝试解析这是scanf("Parent %d", &amp;i) &amp;&amp; i)。这里有两个问题:

  • 'Parent' 中的 'P' 与初始消息中剩余的 '\n' 不匹配
  • 当格式更新为跳过前导空格时,“i”的值将为零,这将导致 while 在读取“父 0”后退出。

可能的解决方案:让scanf跳过空格,并消除i上的条件

    while (scanf(" Parent %d", &i) == 1 )
            printf("Recieved: %d\n", i);

【讨论】:

    【解决方案2】:

    这里的问题在于您的 scanf 语句。按照@dash-o 的建议,将其更改为处理空格。

    另一个问题是,首先是i = 0。您需要修改您的 while 以适应 0。

    由于您只在 while loop 中评估 i,因此您不会进入 ``i=0`` 的情况。

    下面是修改后的程序和输出,另外,如果你认为正确,请添加对函数/缓冲区溢出的返回值的各种检查--

    #include <stdio.h>
    #include <time.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    int main()
    {
            int fd[2];
            int p = pipe(fd);
            int ch = fork();
    
            if (ch)
            {
                    // Parent - Counts from 1 to 3
                    int dp = dup2(fd[1], 1);
                    printf("Cnt_Started_at_%d\n", time(NULL));
                    for (int i = 0; i <= 3; i++)
                    {
                            printf("Parent %d\n", i);
                            sleep(1);
                    }
                    printf("0\n");
                    printf("Cnt_Finished_at_%d\n", time(NULL));
            }
            else
            {
                    // Child - Terminated by 0
                    int dp = dup2(fd[0], 0);
                    printf("Trm_Started_at_%d\n", time(NULL));
                    char buffer[100];
                    scanf("%s", buffer);
                    printf("%s\n", buffer);
    
                    int i;
                    while (scanf(" Parent %d", &i) && i >= 0) // notice change here ...
                            printf("Recieved: %d\n", i);
    
                    scanf("%s", buffer);
                    printf("%s\n", buffer);
                    printf("Trm_Finished_at_%d\n", time(NULL));
            }
    }
    
    OUTPUT --
    $ ./main.out
    Trm_Started_at_1578303662
    Cnt_Started_at_1578303662
    Recieved: 0
    Recieved: 1
    Recieved: 2
    Recieved: 3
    0
    Trm_Finished_at_1578303666
    

    【讨论】:

    • 可以添加更多错误检查 - 例如 fork 失败。 scanf 中的缓冲区也溢出
    • @EdHeal 这段代码只是我试图理解管道。如果我正在编写一个真正的程序,我肯定会这样做。
    • 是的,工作正常。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多