English 中文(简体)
林丹
原标题:Linux got stuck using pipe() and dup2()

我正在模拟铁壳管道运营商,我 go。 下面是我所尝试的最起码的可再生例子。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int do_command(char* args[])
{
    int status;
    pid_t pid = fork();

    if (pid == 0)
    {
        execvp(args[0], args);
    }
    else
    {
        wait(&status);
    }

    return 0;
}

int main() {
    int pipefd[2];
    pid_t pid;

    // Create a pipe
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    // Redirect stdout to write end of the pipe
    if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
        perror("dup2");
        exit(EXIT_FAILURE);
    }

    // the output will go to pipefd[1].
    char* echo[] = { "echo", "Hello, World!", NULL };
    do_command(echo);

    close(pipefd[1]);

    // Redirect stdin to read end of the pipe
    if (dup2(pipefd[0], STDIN_FILENO) == -1) {
        perror("dup2");
        exit(EXIT_FAILURE);
    }

    // since there is no argument to rev, it will automatically read from pipefd[0]
    char* rev[] = { "rev", NULL };
    do_command(rev);

    close(pipefd[0]);

    return 0;
}

在我执政之后,该方案停止了,没有产生任何单一字。 我认为,与<代码>close()有关,但我可以这样说。 我确实关闭了这两个管道。 我怎么能加以纠正?

在不改变<代码>do_command()结构的情况下确定该准则是否有任何办法? 我希望今后模拟多个管道链,因此,我希望职能结构<编码>do_command<>code>保持不变,以便易于称呼指挥。

问题回答

正如我在评论中指出的,由于你将控制过程的标准产出改为管道的核销,因此,如果管理<代码>rev程序,则向管道提交。 它还从管道中读到,管道可以健康。

你还需要在等待完成之前启动儿童进程。

总的来说,你们都需要一大笔rew子。 我在此做的是:

/* SO 7839-3593 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "stderr.h"

static void wait_loop(void)
{
    int corpse;
    int status;
    while ((corpse = wait(&status)) > 0)
        err_remark("child %5d died with status 0x%.4X
", corpse, status);
}

static void do_echo(int fd[2])
{
    if (dup2(fd[1], STDOUT_FILENO) < 0)
        err_syserr("dup2() failed to duplicate fd %d to fd %d: ", fd[1], STDOUT_FILENO);
    close(fd[0]);
    close(fd[1]);
    char *echo[] = { "echo", "Hello, World!", NULL };
    err_remark("executing %s
", echo[0]);
    execvp(echo[0], echo);
    err_syserr("failed to execute %s: ", echo[0]);
    /*NOTREACHED*/
}

static void do_rev(int fd[2])
{
    if (dup2(fd[0], STDIN_FILENO) < 0)
        err_syserr("dup2() failed to duplicate fd %d to fd %d: ", fd[0], STDIN_FILENO);
    close(fd[0]);
    close(fd[1]);
    char *rev[] = { "rev", NULL };
    err_remark("executing %s
", rev[0]);
    execvp(rev[0], rev);
    err_syserr("failed to execute %s: ", rev[0]);
    /*NOTREACHED*/
}

int main(void)
{
    err_setarg0("so-7839-3593");
    err_setlogopts(ERR_PID|ERR_MILLI);
    int pipefd[2];

    // Create a pipe
    if (pipe(pipefd) == -1)
        err_syserr("pipe() failed: ");

    pid_t pid = fork();
    if (pid == -1)
        err_syserr("fork() failed: ");
    if (pid == 0)
        do_echo(pipefd);

    pid = fork();
    if (pid == -1)
        err_syserr("fork() failed: ");
    if (pid == 0)
        do_rev(pipefd);

    close(pipefd[0]);
    close(pipefd[1]);

    wait_loop();

    return 0;
}

This code uses my standard error reporting functions for succinctness. The code for them is available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c and stderr.h in the src/libsoq sub-directory. You could use the err(3) on Linux instead.

<代码>main(>中的代码规定了方案名称和一些伐木选择(途径是书写项目设计书,时间为最接近的周期),然后才输入业务守则。 它创建管道,然后为第一个履行<条码>功能的儿童提供食宿。 然后,将第二名履行以下职能的儿童列入:do_rev()。 然后,它关闭了管道的两端,进入了每名儿童在离开时报到的等候场所。

<代码>do_echo()功能由儿童过程执行。 它把管道的字末与标准产出(儿童向管道书写)相重复,然后关闭了“ 和>echo。 如果execvp() Return,该编码即告失败,err_syserr(功能报告故障和退出。

<代码>do_rev()功能也由儿童程序执行。 它把管道的“末端”与标准投入(即儿童从管道读到)相重复,然后关闭了“ 和><>>> 管道的末端,并在发射失败时发射<> rev的指令、报告故障和撤离。

在我管理该方案的某个时候,我对从<代码>dup2()返回价值进行了 b测试,并得出了产出:

so-7839-3593: 2024-04-26 20:48:41.713 - pid=85728: dup2() failed to duplicate fd 4 to fd 1: error (22) Invalid argument
so-7839-3593: 2024-04-26 20:48:41.714 - pid=85729: executing rev
so-7839-3593: 2024-04-26 20:48:41.714 - pid=85727: child 85728 died with status 0x0100
so-7839-3593: 2024-04-26 20:48:41.717 - pid=85727: child 85729 died with status 0x0000

在我确定试验时,我得出以下产出:

so-7839-3593: 2024-04-26 20:51:48.298 - pid=85802: executing rev
so-7839-3593: 2024-04-26 20:51:48.298 - pid=85801: executing echo
!dlroW ,olleH
so-7839-3593: 2024-04-26 20:51:48.302 - pid=85800: child 85801 died with status 0x0000
so-7839-3593: 2024-04-26 20:51:48.302 - pid=85800: child 85802 died with status 0x0000

当你重新测试多加工管道时,确保你拥有与生产过程的公投数据库适当挂钩的cop缩产出。





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签