C中多管道的实现

发布于 2024-12-20 00:22:28 字数 3020 浏览 1 评论 0原文

我正在尝试在 C 语言的 shell 中实现多个管道。我找到了一个关于此的教程 网站,我做的功能就是基于这个例子。这是该函数

void executePipes(cmdLine* command, char* userInput) {
    int numPipes = 2 * countPipes(userInput);
    int status;
    int i = 0, j = 0;
    int pipefds[numPipes];

    for(i = 0; i < (numPipes); i += 2)
        pipe(pipefds + i);

    while(command != NULL) {
        if(fork() == 0){

            if(j != 0){
                dup2(pipefds[j - 2], 0);
            }

            if(command->next != NULL){
                dup2(pipefds[j + 1], 1);
            }    

            for(i = 0; i < (numPipes); i++){
                close(pipefds[i]);
            }
            if( execvp(*command->arguments, command->arguments) < 0 ){
                perror(*command->arguments);
                exit(EXIT_FAILURE);
            }
        }

        else{
                if(command != NULL)
                    command = command->next;

                j += 2;
                for(i = 0; i < (numPipes ); i++){
                   close(pipefds[i]);
                }
               while(waitpid(0,0,0) < 0);
        }
    }

}

执行后并输入命令,例如 ls | grep bin,shell 只是挂在那里并且不输出任何结果。我确保关闭了所有管道。但它只是挂在那里。我认为问题出在 waitpid 上。我删除了 waitpid ,执行后没有得到任何结果。我做错了什么?谢谢。

添加的代码:

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);

    int status;
    int i = 0, j = 0;

    pid_t pid;

    int pipefds[2*numPipes];

    for(i = 0; i < 2*(numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }

    while(command) {
        pid = fork();
        if(pid == 0) {

            //if not first command
            if(j != 0){
                if(dup2(pipefds[(j-1) * 2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);
                    //printf("j != 0  dup(pipefd[%d], 0])\n", j-2);
                }
            //if not last command
            if(command->next){
                if(dup2(pipefds[j * 2 + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
            }

            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;
        j++;
    }
        for(i = 0; i < 2 * numPipes; i++){
            close(pipefds[i]);
            puts("closed pipe in parent");
        }

        while(waitpid(0,0,0) <= 0);

    }

}

I'm trying to implement multiple pipes in my shell in C. I found a tutorial on this website and the function I made is based on this example. Here's the function

void executePipes(cmdLine* command, char* userInput) {
    int numPipes = 2 * countPipes(userInput);
    int status;
    int i = 0, j = 0;
    int pipefds[numPipes];

    for(i = 0; i < (numPipes); i += 2)
        pipe(pipefds + i);

    while(command != NULL) {
        if(fork() == 0){

            if(j != 0){
                dup2(pipefds[j - 2], 0);
            }

            if(command->next != NULL){
                dup2(pipefds[j + 1], 1);
            }    

            for(i = 0; i < (numPipes); i++){
                close(pipefds[i]);
            }
            if( execvp(*command->arguments, command->arguments) < 0 ){
                perror(*command->arguments);
                exit(EXIT_FAILURE);
            }
        }

        else{
                if(command != NULL)
                    command = command->next;

                j += 2;
                for(i = 0; i < (numPipes ); i++){
                   close(pipefds[i]);
                }
               while(waitpid(0,0,0) < 0);
        }
    }

}

After executing it and typing a command like for example ls | grep bin, the shell just hangs there and doesn't output any result. I made sure I closed all pipes. But it just hangs there. I thought that it was the waitpid that's was the problem. I removed the waitpid and after executing I get no results. What did I do wrong? Thanks.

Added code:

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);

    int status;
    int i = 0, j = 0;

    pid_t pid;

    int pipefds[2*numPipes];

    for(i = 0; i < 2*(numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }

    while(command) {
        pid = fork();
        if(pid == 0) {

            //if not first command
            if(j != 0){
                if(dup2(pipefds[(j-1) * 2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);
                    //printf("j != 0  dup(pipefd[%d], 0])\n", j-2);
                }
            //if not last command
            if(command->next){
                if(dup2(pipefds[j * 2 + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
            }

            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;
        j++;
    }
        for(i = 0; i < 2 * numPipes; i++){
            close(pipefds[i]);
            puts("closed pipe in parent");
        }

        while(waitpid(0,0,0) <= 0);

    }

}

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

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

发布评论

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

评论(6

烟沫凡尘 2024-12-27 00:22:28

我认为这里的问题是您的等待和关闭在创建子项的同一个循环内。在第一次迭代中,子进程将执行(这将销毁子程序,用您的第一个命令覆盖它),然后父进程关闭其所有文件描述符并等待子进程完成,然后再迭代创建下一个子进程。此时,由于父级已关闭其所有管道,因此任何其他子级将无法写入或读取任何内容。由于您没有检查 dup2 调用是否成功,因此不会注意到这一点。

如果您想保持相同的循环结构,则需要确保父级仅关闭已使用的文件描述符,而保留那些未使用的文件描述符。然后,在创建所有子项之后,您的父项就可以等待了。

编辑:我在答案中混淆了父/子,但推理仍然成立:再次分叉的进程会关闭其所有管道副本,因此第一个分叉之后的任何进程将没有有效的文件描述符可供读取/写入。

伪代码,使用预先创建的管道数组:

/* parent creates all needed pipes at the start */
for( i = 0; i < num-pipes; i++ ){
    if( pipe(pipefds + i*2) < 0 ){
        perror and exit
    }
}

commandc = 0
while( command ){
    pid = fork()
    if( pid == 0 ){
        /* child gets input from the previous command,
            if it's not the first command */
        if( not first command ){
            if( dup2(pipefds[(commandc-1)*2], 0) < ){
                perror and exit
            }
        }
        /* child outputs to next command, if it's not
            the last command */
        if( not last command ){
            if( dup2(pipefds[commandc*2+1], 1) < 0 ){
                perror and exit
            }
        }
        close all pipe-fds
        execvp
        perror and exit
    } else if( pid < 0 ){
        perror and exit
    }
    cmd = cmd->next
    commandc++
}

/* parent closes all of its copies at the end */
for( i = 0; i < 2 * num-pipes; i++ ){
    close( pipefds[i] );
}

在此代码中,原始父进程为每个命令创建一个子进程,因此在整个考验中幸存下来。孩子们检查是否应该从上一个命令获取输入以及是否应该将输出发送到下一个命令。然后他们关闭管道文件描述符的所有副本,然后执行。父级除了 fork 之外什么都不做,直到它为每个命令创建了一个子级。然后它关闭所有描述符副本并可以继续等待。

首先创建所需的所有管道,然后在循环中管理它们,这是很棘手的并且需要一些数组算术。不过,目标看起来像这样:

cmd0    cmd1   cmd2   cmd3   cmd4
   pipe0   pipe1  pipe2  pipe3
   [0,1]   [2,3]  [4,5]  [6,7]

认识到在任何给定时间,您只需要两组管道(上一个命令的管道和下一个命令的管道)将简化您的代码并使其更加健壮。 Ehemient 在此处提供了伪代码。他的代码更干净,因为父级和子级不必执行不必要的循环来关闭不需要的文件描述符,并且父级可以在分叉后立即轻松关闭其文件描述符的副本。

附带说明:您应该始终检查 pipeline、dup2、fork 和 exec 的返回值。

编辑2:伪代码中的拼写错误。 OP:num-pipes 是管道的数量。例如,“ls | grep foo | sort -r”将有 2 个管道。

I believe the issue here is that your waiting and closing inside the same loop that's creating children. On the first iteration, the child will exec (which will destroy the child program, overwriting it with your first command) and then the parent closes all of its file descriptors and waits for the child to finish before it iterates on to creating the next child. At that point, since the parent has closed all of its pipes, any further children will have nothing to write to or read from. Since you are not checking for the success of your dup2 calls, this is going un-noticed.

If you want to keep the same loop structure, you'll need to make sure the parent only closes the file descriptors that have already been used, but leaves those that haven't alone. Then, after all children have been created, your parent can wait.

EDIT: I mixed up the parent/child in my answer, but the reasoning still holds: the process that goes on to fork again closes all of its copies of the pipes, so any process after the first fork will not have valid file descriptors to read to/write from.

pseudo code, using an array of pipes created up-front:

/* parent creates all needed pipes at the start */
for( i = 0; i < num-pipes; i++ ){
    if( pipe(pipefds + i*2) < 0 ){
        perror and exit
    }
}

commandc = 0
while( command ){
    pid = fork()
    if( pid == 0 ){
        /* child gets input from the previous command,
            if it's not the first command */
        if( not first command ){
            if( dup2(pipefds[(commandc-1)*2], 0) < ){
                perror and exit
            }
        }
        /* child outputs to next command, if it's not
            the last command */
        if( not last command ){
            if( dup2(pipefds[commandc*2+1], 1) < 0 ){
                perror and exit
            }
        }
        close all pipe-fds
        execvp
        perror and exit
    } else if( pid < 0 ){
        perror and exit
    }
    cmd = cmd->next
    commandc++
}

/* parent closes all of its copies at the end */
for( i = 0; i < 2 * num-pipes; i++ ){
    close( pipefds[i] );
}

In this code, the original parent process creates a child for each command and therefore survives the entire ordeal. The children check to see if they should get their input from the previous command and if they should send their output to the next command. Then they close all of their copies of the pipe file descriptors and then exec. The parent doesn't do anything but fork until it's created a child for each command. It then closes all of its copies of the descriptors and can go on to wait.

Creating all of the pipes you need first, and then managing them in the loop, is tricky and requires some array arithmetic. The goal, though, looks like this:

cmd0    cmd1   cmd2   cmd3   cmd4
   pipe0   pipe1  pipe2  pipe3
   [0,1]   [2,3]  [4,5]  [6,7]

Realizing that, at any given time, you only need two sets of pipes (the pipe to the previous command and the pipe to the next command) will simplify your code and make it a little more robust. Ephemient gives pseudo-code for this here. His code is cleaner, because the parent and child do not have to do unnecessary looping to close un-needed file descriptors and because the parent can easily close its copies of the file descriptors immediately after the fork.

As a side note: you should always check the return values of pipe, dup2, fork, and exec.

EDIT 2: typo in pseudo code. OP: num-pipes would be the number of pipes. E.g., "ls | grep foo | sort -r" would have 2 pipes.

小红帽 2024-12-27 00:22:28

这是正确的功能代码

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);


    int status;
    int i = 0;
    pid_t pid;

    int pipefds[2*numPipes];

    for(i = 0; i < (numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("couldn't pipe");
            exit(EXIT_FAILURE);
        }
    }


    int j = 0;
    while(command) {
        pid = fork();
        if(pid == 0) {

            //if not last command
            if(command->next){
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            //if not first command&& j!= 2*numPipes
            if(j != 0 ){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);

                }
            }


            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
            }

            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;
        j+=2;
    }
    /**Parent closes the pipes and wait for children*/

    for(i = 0; i < 2 * numPipes; i++){
        close(pipefds[i]);
    }

    for(i = 0; i < numPipes + 1; i++)
        wait(&status);
}

Here's the correct functioning code

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);


    int status;
    int i = 0;
    pid_t pid;

    int pipefds[2*numPipes];

    for(i = 0; i < (numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("couldn't pipe");
            exit(EXIT_FAILURE);
        }
    }


    int j = 0;
    while(command) {
        pid = fork();
        if(pid == 0) {

            //if not last command
            if(command->next){
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            //if not first command&& j!= 2*numPipes
            if(j != 0 ){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);

                }
            }


            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
            }

            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;
        j+=2;
    }
    /**Parent closes the pipes and wait for children*/

    for(i = 0; i < 2 * numPipes; i++){
        close(pipefds[i]);
    }

    for(i = 0; i < numPipes + 1; i++)
        wait(&status);
}
凉城凉梦凉人心 2024-12-27 00:22:28

(缩短的)相关代码是:

    if(fork() == 0){
            // do child stuff here
            ....
    }
    else{
            // do parent stuff here
            if(command != NULL)
                command = command->next;

            j += 2;
            for(i = 0; i < (numPipes ); i++){
               close(pipefds[i]);
            }
           while(waitpid(0,0,0) < 0);
    }

这意味着父(控制)进程执行以下操作:

  • fork
  • close all Pipes
  • wait for child process
  • next loop / child

但它应该是这样的:

  • fork
  • fork
  • fork
  • close all pipeline (一切都应该是现在被骗了)
  • 等待孩子们

The (shortened) relevant code is:

    if(fork() == 0){
            // do child stuff here
            ....
    }
    else{
            // do parent stuff here
            if(command != NULL)
                command = command->next;

            j += 2;
            for(i = 0; i < (numPipes ); i++){
               close(pipefds[i]);
            }
           while(waitpid(0,0,0) < 0);
    }

Which means the parent (controlling) process does this:

  • fork
  • close all pipes
  • wait for child process
  • next loop / child

But it should be something like this:

  • fork
  • fork
  • fork
  • close all pipes (everything should have been duped now)
  • wait for childs
伴我心暖 2024-12-27 00:22:28

您只需要两个管道交替,如下所示:

typedef int io[2];

extern int I; //piped command current index
extern int pipe_count; //count of '|'

#define CURRENT 0
#define PREVIOUS 1
#define READ 0
#define WRITE 1
#define is_last_command (I == pipe_count)

bool connect(io pipes[2])
{
    if (pipe_count)
    {
        if (is_last_command || I != 0)
            dup2(pipes[PREVIOUS][READ], STDIN_FILENO);
        if (I == 0 || !is_last_command)
            dup2(pipes[CURRENT][WRITE], STDOUT_FILENO);
    }
    return (true);
}

void close_(io pipes[2])
{
    if (pipe_count)
    {
        if (is_last_command || I != 0)
            close(pipes[PREVIOUS][READ]);
        if (I == 0 || !is_last_command)
            close(pipes[CURRENT][WRITE]);
    }
}

void alternate(int **pipes)
{
    int *pipe_current;

    pipe_current = pipes[CURRENT];
    pipes[CURRENT] = pipes[PREVIOUS];
    pipes[PREVIOUS] = pipe_current;
}

示例用法:

#define ERROR -1
#define CHILD 0

void execute(char **command)
{
    static io pipes[2];

    if (pipe_count && pipe(pipes[CURRENT]) == ERROR)
        exit_error("pipe");
    if (fork()==CHILD && connect(pipes))
    {
        execvp(command[0], command);
        _exit(EXIT_FAILURE);
    }
    while (wait(NULL) >= 0);
    close_(pipes);
    alternate((int **)pipes);
}

static void run(char ***commands)
{
    for (I = 0; commands[I]; I++)
        if (*commands[I])
            execute(commands[I]);
}

我将留下一个 链接 到完整的工作代码给有需要的人。

You only need two pipes alternating like below:

typedef int io[2];

extern int I; //piped command current index
extern int pipe_count; //count of '|'

#define CURRENT 0
#define PREVIOUS 1
#define READ 0
#define WRITE 1
#define is_last_command (I == pipe_count)

bool connect(io pipes[2])
{
    if (pipe_count)
    {
        if (is_last_command || I != 0)
            dup2(pipes[PREVIOUS][READ], STDIN_FILENO);
        if (I == 0 || !is_last_command)
            dup2(pipes[CURRENT][WRITE], STDOUT_FILENO);
    }
    return (true);
}

void close_(io pipes[2])
{
    if (pipe_count)
    {
        if (is_last_command || I != 0)
            close(pipes[PREVIOUS][READ]);
        if (I == 0 || !is_last_command)
            close(pipes[CURRENT][WRITE]);
    }
}

void alternate(int **pipes)
{
    int *pipe_current;

    pipe_current = pipes[CURRENT];
    pipes[CURRENT] = pipes[PREVIOUS];
    pipes[PREVIOUS] = pipe_current;
}

Example usage:

#define ERROR -1
#define CHILD 0

void execute(char **command)
{
    static io pipes[2];

    if (pipe_count && pipe(pipes[CURRENT]) == ERROR)
        exit_error("pipe");
    if (fork()==CHILD && connect(pipes))
    {
        execvp(command[0], command);
        _exit(EXIT_FAILURE);
    }
    while (wait(NULL) >= 0);
    close_(pipes);
    alternate((int **)pipes);
}

static void run(char ***commands)
{
    for (I = 0; commands[I]; I++)
        if (*commands[I])
            execute(commands[I]);
}

I'll leave a link to a full working code for someone who needs it.

无声无音无过去 2024-12-27 00:22:28

基于 Christopher Neylan 提到的在给定时间最多使用两个管道的想法,我编写了 n 管道的伪代码。 args 是大小为“args_size”的字符指针数组,它是一个全局变量。

// MULTIPLE PIPES
// Test case:   char *args[] = {"ls", "-l", "|", "head", "|", "tail", "-4", 
0};// "|", "grep", "Txt", 0};   
enum fileEnd{READ, WRITE};

void multiple pipes( char** args){
pid_t cpid;
// declare pipes
int pipeA[2]
int pipeB[2]
// I have done getNumberofpipes
int numPipes = getNumberOfPipes;
int command_num = numPipes+1;
// holds sub array of args 
// which is a statement to execute
// for example: cmd = {"ls", "-l", NULL}
char** cmd 
// iterate over args
for(i = 0; i < args_size; i++){
  // 
  // strip subarray from main array
  //  cmd 1 | cmd 2 | cmd3 => cmd
  // cmd = {"ls", "-l", NULL}
  //Open/reopen one pipe

  //if i is even open pipeB
    if(i % 2)  pipe(pipeB);
  //if i is odd open pipeA
    else       pipe(pipeA);


  switch(cpid = fork(){
      case -1: error forking
      case 0: // child process
            childprocess(i);
      default: // parent process
           parentprocess(i, cpid);
  }
}
}
// parent pipes must be closed in parent
void parentprocess(int i, pid_t cpid){

   // if first command
   if(i == 0)  
        close(pipeB[WRITE]);

   // if last command close WRITE
   else if (i == numPipes){
       // if i is even close pipeB[WRITE]
       // if i is odd close pipeA[WRITE]
   }

   // otherwise if in middle close READ and WRITE 
   // for appropriate pipes
      // if i is even
      close(pipeA[READ])
      close(pipeB[WRITE])
      // if i is odd
      close(pipeB[READ])
      close(pipeA[WRITE])
   }

   int returnvalue, status;
   waitpid(cpid, returnvalue, status);
}
void childprocess(int i){

    // if in first command
    if(i == 0)
        dup2(pipeB[WRITE], STDOUT_FILENO);
    //if in last command change stdin for
    // the necessary pipe. Don't touch stdout - 
    // stdout goes to shell
    else if( numPipes == i){
        // if i is even
        dup2(pipeB[READ], STDIN_FILENO)
        //if i is odd
        dup2(pipeA[READ], STDIN_FILENO);        
    }
    // otherwise, we are in middle command where
    // both pipes are used.
    else{
       // if i is even
       dup2(pipeA[READ], STDIN_FILENO)
       dupe(pipeB[WRITE], STDOUT_FILENO)
       // if i is odd
       dup2(pipeB[READ], STDIN_FILENO)
       dup2(pipeA[WRITE], STDOUT_FILENO)
    }

    // execute command for this iteration
    // check for errors!!
    // The exec() functions only return if an error has occurred. The return value is -1, and errno is set to indicate the error.
    if(exec(cmd, cmd) < 0)
        printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
    }   
}

Building upon the idea of using a maximum of two pipes at a given time mentioned by Christopher Neylan, I put together pseudocode for n-pipes. args is an array of character pointers of size 'args_size' which is a global variable.

// MULTIPLE PIPES
// Test case:   char *args[] = {"ls", "-l", "|", "head", "|", "tail", "-4", 
0};// "|", "grep", "Txt", 0};   
enum fileEnd{READ, WRITE};

void multiple pipes( char** args){
pid_t cpid;
// declare pipes
int pipeA[2]
int pipeB[2]
// I have done getNumberofpipes
int numPipes = getNumberOfPipes;
int command_num = numPipes+1;
// holds sub array of args 
// which is a statement to execute
// for example: cmd = {"ls", "-l", NULL}
char** cmd 
// iterate over args
for(i = 0; i < args_size; i++){
  // 
  // strip subarray from main array
  //  cmd 1 | cmd 2 | cmd3 => cmd
  // cmd = {"ls", "-l", NULL}
  //Open/reopen one pipe

  //if i is even open pipeB
    if(i % 2)  pipe(pipeB);
  //if i is odd open pipeA
    else       pipe(pipeA);


  switch(cpid = fork(){
      case -1: error forking
      case 0: // child process
            childprocess(i);
      default: // parent process
           parentprocess(i, cpid);
  }
}
}
// parent pipes must be closed in parent
void parentprocess(int i, pid_t cpid){

   // if first command
   if(i == 0)  
        close(pipeB[WRITE]);

   // if last command close WRITE
   else if (i == numPipes){
       // if i is even close pipeB[WRITE]
       // if i is odd close pipeA[WRITE]
   }

   // otherwise if in middle close READ and WRITE 
   // for appropriate pipes
      // if i is even
      close(pipeA[READ])
      close(pipeB[WRITE])
      // if i is odd
      close(pipeB[READ])
      close(pipeA[WRITE])
   }

   int returnvalue, status;
   waitpid(cpid, returnvalue, status);
}
void childprocess(int i){

    // if in first command
    if(i == 0)
        dup2(pipeB[WRITE], STDOUT_FILENO);
    //if in last command change stdin for
    // the necessary pipe. Don't touch stdout - 
    // stdout goes to shell
    else if( numPipes == i){
        // if i is even
        dup2(pipeB[READ], STDIN_FILENO)
        //if i is odd
        dup2(pipeA[READ], STDIN_FILENO);        
    }
    // otherwise, we are in middle command where
    // both pipes are used.
    else{
       // if i is even
       dup2(pipeA[READ], STDIN_FILENO)
       dupe(pipeB[WRITE], STDOUT_FILENO)
       // if i is odd
       dup2(pipeB[READ], STDIN_FILENO)
       dup2(pipeA[WRITE], STDOUT_FILENO)
    }

    // execute command for this iteration
    // check for errors!!
    // The exec() functions only return if an error has occurred. The return value is -1, and errno is set to indicate the error.
    if(exec(cmd, cmd) < 0)
        printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
    }   
}
陌伤浅笑 2024-12-27 00:22:28

基本上,您想要做的是一个递归函数,其中子级执行第一个命令,如果没有其他命令,则父级执行第二个命令再次调用该函数。

Basically what you wanna do is a recursive function where the child executes the first command and the parent executes the second one if no other commands are left or calls the function again.

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