c - C 的管道问题。是否有额外的进程正在执行?

标签 c pipe multiple-processes

我不知道这段代码有什么问题。其输出存在多个错误。该程序应该模仿 UNIX shell。只要不包含任何管道,它就可以正常运行任何命令。然而,当我添加管道时,有趣的事情开始发生。

例如:当我输入 sort < myshell1,c | grep main | cat > o.txt

它创建了一个额外的进程。您可以看到这一点,因为在代码中,perror(in)被执行 4 次(根据 GDB):

COP4338$ sort < myshell1.c | grep main | cat > o.txt
Detaching after fork from child process 16465.
Process ID: 16465
Process ID: 0
in: Success
Detaching after fork from child process 16466.
Process ID: 16466
Process ID: 0
in: Success
Something happened in i != numcommands - 1: Success
Detaching after fork from child process 16468.
Process ID: 16468
COP4338$ Process ID: 0
in: Success
ELSE STATEMENT!
Detaching after fork from child process 17403.
in: Bad address

然后,程序转到新行并且不打印 COP4338$:就像它应该的那样。表现出未定义的行为。我猜测为什么会发生这种情况,因为第四个进程也在继续,因此返回到 main(),就像父进程一样,但我无法确定为什么要创建它。

当我尝试运行 ls -l | cat > o.txt 时,也会出现未定义的行为。

这是 GDB 的输出:

就尝试解决该问题而言,我尚未确定导致此问题的原因。我尝试使用 gdb 调试器通过键入“set follow-fork-mode child”并在第三个子进程的第一行使用断点来调试第三个子进程,但没有任何反应。我只能通过这样做来调试第一个子进程。

/* This code  was written by Dr. Raju Rangaswami and was expanded upon as per the instructions in Assignment3, by Michael Duboc(PID: 5706538)*/

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#define MAX_ARGS 20
#define BUFSIZ 1024


int get_args(char* cmdline, char* args[]) 
{
  int i = 0;

  /* if no args */
  if((args[0] = strtok(cmdline, "\n\t ")) == NULL) 
    return 0; 

  while((args[++i] = strtok(NULL, "\n\t ")) != NULL) 
  {
    if(i >= MAX_ARGS) 
    {
      printf("Too many arguments!\n");
      exit(1);
    }
  }
  /* the last one is always NULL */
  return i;
}




int customStrCpy(char** line1, char* line2)
{
    int strlen1 = strlen(*line1), strlen2 = strlen(line2);
    if(strlen1 < strlen2)
    {
        //Creates a dynamically allocated array that is big enough to store the contents of line2.
        *line1 = calloc(strlen2, sizeof(char));

    }
    strcpy(*line1, line2);



}




void adjustArray(char* args[], int args_itr, int* nargs)
{

    int i, j;

    for(i = 0; i < 2; i++)
    {

        for(j = args_itr; j < (*nargs) - 1; j++)
        {
            customStrCpy(&args[j],args[j+1]);
        }
        args[(*nargs) - 1] = 0;
        (*nargs)--;
        }

} 

int process(int* greaterthan, int* d_greaterthan, char* args_pipe[], int* 
nargs_p, int* fileno_out, int* fileno_in, int* lessthan, FILE** fout, 
FILE** fin)
{
    int greaterthan_strcmp = strcmp(args_pipe[args_itr], ">");
    int d_greaterthan_strcmp = strcmp(args_pipe[args_itr], ">>");
            if(greaterthan_strcmp == 0 || d_greaterthan_strcmp  == 0)
            {
                    if(greaterthan_strcmp == 0)
                            *fout = fopen(args_pipe[args_itr + 1], "w");
                    else
                            *fout = fopen(args_pipe[args_itr + 1], "a");
                    *fileno_out = fileno(*fout);

                    *greaterthan = 1;
                    adjustArray(args_pipe, args_itr, nargs_p);
                    args_itr--;
                    int print_arr;
                    for(print_arr = 0; print_arr 
                      (sizeof(args_pipe)/sizeof(args_pipe[0])); print_arr++) 
                      printf("%s ",args_pipe[print_arr]);
                    printf("\n");
            }





         else if(strcmp(args_pipe[args_itr], "<") == 0)
         {


            *fin = fopen(args_pipe[args_itr + 1], "r");
            *fileno_in = fileno(*fin);

            *lessthan = 1;
            adjustArray(args_pipe, args_itr, nargs_p);
            args_itr--;

        }

    }


    return 0;


}




void execute(char* cmdline) 
{
  int pid, async, lessthan = 0;
  int greaterthan = 0, pipef = 0, d_greaterthan = 0;
  int args_itr, pipe_flag = 0;
  int flag_count = 0, fileno_in, fileno_out;
  char* args_pipe[MAX_ARGS];/*5 and 3 are test numbers.*/
  char* args[MAX_ARGS];


  int nargs = get_args(cmdline, args);
  if(nargs <= 0) return;

  if(!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) 
  {

    exit(0);
  }

  /* check if async call */
  if(!strcmp(args[nargs-1], "&")) { async = 1; args[--nargs] = 0; }
  else async = 0;
  FILE* fout = stdout;
  FILE* fin = stdin; 
  for(args_itr = 0; args_itr < nargs; args_itr++)
  {
    if(!strcmp(args[args_itr], "|")) {pipe_flag = 1; flag_count++;}
    }



  if(pipe_flag)
  {
    int num_commands = flag_count + 1, i = 0, j = 0;
    int fd[num_commands][2];


    for(i = 0; i < flag_count; i++) {pipe(fd[i]);}

    for(i = 0; i < num_commands; i++)
    {


        int nargs_p = 0, args_pipe_itr = 0;
        while(j < nargs && strcmp(args[j], "|")) 
        {//Possibly make into for loop.
            args_pipe[args_pipe_itr] = args[j]; 
            args_pipe_itr++; 
            j++; 
            nargs_p++;
        }

        j++;    


        int pid = fork();

        signal(SIGTTIN, SIG_IGN);
        signal(SIGTTOU, SIG_IGN);   
        printf("Process ID: %d\n", pid);    

        if(pid < 0)
        {
            perror("Error forking!");
            return;
        }

        else if(pid > 0) {continue;}

        else //pid == 0
        {

            perror("in");
            if(i == 0)
            {   
                process(&greaterthan, &d_greaterthan, &args_pipe[i] ,&nargs_p, &fileno_out, &fileno_in, &lessthan, &fout, &fin);
                printf("Lessthan = %d", lessthan);                               
                if(lessthan) dup2(fileno_in, STDIN_FILENO);
                dup2(fd[i][1], STDOUT_FILENO);

                }

            else if(i != num_commands - 1)
            {

                 dup2(fd[i - 1][1], STDIN_FILENO);

            //process(&greaterthan, &d_greaterthan, &args_pipe[i] ,&nargs_p, &fileno_out, &fileno_in, &lessthan, &fout, &fin);

                dup2(fd[i][1], STDOUT_FILENO);
            }

            else
            {           
                dup2(fd[i - 1][1], STDIN_FILENO);   
                process(&greaterthan, &d_greaterthan, &args_pipe[i] ,&nargs_p, &fileno_out, &fileno_in, &lessthan, &fout, &fin);

                printf("greaterthan = %d", greaterthan);
                printf("d_greaterthan = %d", d_greaterthan);
                if(greaterthan || d_greaterthan) dup2(fileno_out, STDOUT_FILENO);    
                }

            int close_pipes;
            for(close_pipes = 0; close_pipes < flag_count; close_pipes++) 
            {
                //close(fd[i][0]); close(fd[i][1]); JUST, WHY?!? THIS IS WHAT HAPPENS WHEN YOU DON'T THINK!

                close(fd[close_pipes][0]);
                close(fd[close_pipes][1]);
            }
            if(fout != stdout) fclose(fout);
            if(fin != stdin) fclose(fin);
            execvp(args_pipe[0], args_pipe);
            perror("Something happened.");
            exit(-1);
       }//end child.




    }   
        for(i = 0; i < flag_count; i++) {close(fd[i][0]); close(fd[i][1]);}
        return;

    }


 }

int main (int argc, char* argv [])
{
      for(;;)
      {
          printf("COP4338$ ");

         if(fgets(cmdline, BUFSIZ, stdin) == NULL)
         {

             perror("fgets failed");
             exit(1);
         }
            execute(cmdline);
            int corpse;
            int status;
            while(corpse = wait(%status)) > 0)
                perror(pid %d exited with status: 0x%.4X\n, corpse, status);
       }

}

程序应该将“int main (int argc, char* argv [])”打印到o.txt,但o.txt根本没有改变。

对于那些好奇的人来说,函数 process() 会扫描构成命令的参数字符串,并根据程序看到的符号设置标志。

最佳答案

您的代码存在一些问题:

  • 不调用 wait() 或等效函数。
  • 将管道的错误一端连接到标准输入或标准输出。
  • 访问参数组的错误部分 - 命令名称和参数。
  • 关闭错误的管道文件描述符,可能会重复关闭。

我认为 customStrCpy() 函数和 adjustArray() 函数中存在内存泄漏和不必要的内存分配问题,但我还没有解决这些问题 -当您不需要担心泄漏时,代码似乎可以正常工作。

我需要添加诊断来找出您的代码做错了什么。因此,我使用了我的 SOQ 中提供的错误报告代码。 (堆栈溢出问题)GitHub 上的存储库为 src/libsoq 中的文件 stderr.cstderr.h子目录。

此代码基于 Revision 6 中显示的代码问题的内容 - 问题中显示的代码自那时起已被修改。

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

#include "stderr.h"

#define MAX_ARGS 20
#define BUFSIZ 1024

static
int get_args(char *cmdline, char *args[])
{
    int i = 0;

    /* if no args */
    if ((args[0] = strtok(cmdline, "\n\t ")) == NULL)
        return 0;

    while ((args[++i] = strtok(NULL, "\n\t ")) != NULL)
    {
        if (i >= MAX_ARGS)
        {
            printf("Too many arguments!\n");
            exit(1);
        }
    }
    /* the last one is always NULL */
    return i;
}

static
void customStrCpy(char **line1, char *line2)
{
    int strlen1 = strlen(*line1), strlen2 = strlen(line2);
    if (strlen1 < strlen2)
    {
        // Creates a dynamically allocated array that is big enough to store the contents of line2.
        *line1 = calloc(strlen2, sizeof(char));
    }
    strcpy(*line1, line2);
}

static
void adjustArray(char *args[], int args_itr, int *nargs)
{
    int i, j;

    for (i = 0; i < 2; i++)
    {
        for (j = args_itr; j < (*nargs) - 1; j++)
        {
            customStrCpy(&args[j], args[j + 1]);
        }
        args[(*nargs) - 1] = 0;
        (*nargs)--;
    }
}

static
void process(int *greaterthan, int *d_greaterthan, char *args_pipe[],
             int *nargs_p, int *fileno_out, int *fileno_in, int *lessthan,
             FILE **fout, FILE **fin)
{
    int args_itr;
    err_remark("-->> %s():\n", __func__);
    for (args_itr = 0; args_itr < *nargs_p; args_itr++)
    {
        if (strcmp(args_pipe[args_itr], ">") == 0)
        {
            err_remark("---- %s(): > %s\n", __func__, args_pipe[args_itr + 1]);
            *fout = fopen(args_pipe[args_itr + 1], "w");
            if (fout == NULL)
                err_syserr("failed to open file '%s' for writing\n",
                           args_pipe[args_itr + 1]);
            *fileno_out = fileno(*fout);
            *greaterthan = 1;
            adjustArray(args_pipe, args_itr, nargs_p);
            args_itr--;
        }
        else if (strcmp(args_pipe[args_itr], ">>") == 0)
        {
            err_remark("---- %s(): >> %s\n", __func__, args_pipe[args_itr + 1]);
            *fout = fopen(args_pipe[args_itr + 1], "a");
            if (fout == NULL)
                err_syserr("failed to open file '%s' for appending\n",
                           args_pipe[args_itr + 1]);
            *fileno_out = fileno(*fout);
            *d_greaterthan = 1;
            adjustArray(args_pipe, args_itr, nargs_p);
            args_itr--;
        }
        else if (strcmp(args_pipe[args_itr], "<") == 0)
        {
            err_remark("---- %s(): < %s\n", __func__, args_pipe[args_itr + 1]);
            *fin = fopen(args_pipe[args_itr + 1], "r");
            if (fin == NULL)
                err_syserr("failed to open file '%s' for reading\n",
                           args_pipe[args_itr + 1]);
            *fileno_in = fileno(*fin);
            *lessthan = 1;
            adjustArray(args_pipe, args_itr, nargs_p);
            args_itr--;
        }
    }
    err_remark("<<-- %s()\n", __func__);
}

static
void execute(char *cmdline)
{
    int lessthan = 0;
    int greaterthan = 0, d_greaterthan = 0;
    int args_itr, pipe_flag = 0;
    int flag_count = 0, fileno_in, fileno_out;
    char *args_pipe[MAX_ARGS];/*5 and 3 are test numbers.*/
    char *args[MAX_ARGS];

    int nargs = get_args(cmdline, args);
    if (nargs <= 0)
        return;

    if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit"))
    {
        exit(0);
    }

    for (int x = 0; x < nargs; x++)
        err_remark("args[%d] = [%s]\n", x, args[x]);

    FILE *fout = stdout;
    FILE *fin = stdin;
    for (args_itr = 0; args_itr < nargs; args_itr++)
    {
        if (!strcmp(args[args_itr], "|"))
        {
            pipe_flag = 1;
            flag_count++;
        }
    }

    if (pipe_flag)
    {
        int num_commands = flag_count + 1, i = 0, j = 0;
        int fd[flag_count][2];

        for (i = 0; i < flag_count; i++)
        {
            pipe(fd[i]);
            err_remark("opened pipe - %d and %d\n", fd[i][0], fd[i][1]);
        }

        for (i = 0; i < num_commands; i++)
        {
            int nargs_p = 0, args_pipe_itr = 0;
            while (j < nargs && strcmp(args[j], "|"))
            {
                // Possibly make into for loop.
                args_pipe[args_pipe_itr] = args[j];
                args_pipe_itr++;
                j++;
                nargs_p++;
            }
            args_pipe[nargs_p] = NULL;  /* JL: Null-terminate argument list */

            j++;    /* Skip pipe argument */

            int pid = fork();

            signal(SIGTTIN, SIG_IGN);
            signal(SIGTTOU, SIG_IGN);

            if (pid < 0)
            {
                err_syserr("failed to fork a child process: ");
                /*NOTREACHED*/
            }
            if (pid > 0)
            {
                err_remark("Parent launched child %d\n", pid);
                continue;
            }
            else // if (pid == 0)
            {
                err_remark("child at work (i == %d)\n", i);
                if (i == 0)
                {
                    err_remark("first process in pipeline (i = %d, j = %d)\n", i, j);
                    process(&greaterthan, &d_greaterthan, args_pipe,
                            &nargs_p, &fileno_out, &fileno_in, &lessthan,
                            &fout, &fin);
                    if (lessthan)
                        dup2(fileno_in, STDIN_FILENO);
                    dup2(fd[i][1], STDOUT_FILENO);
                }
                else if (i != num_commands - 1)
                {
                    err_remark("middle process in pipeline (i = %d, j = %d)\n", i, j);
                    dup2(fd[i - 1][0], STDIN_FILENO);   /* JL */
                    /* Will need to process I/O redirections mid-pipeline */
                    /* However, they're always a bug in the shell script */
                    dup2(fd[i][1], STDOUT_FILENO);
                }
                else
                {
                    err_remark("final process in pipeline (i = %d, j = %d)\n", i, j);
                    dup2(fd[i - 1][0], STDIN_FILENO);   /* JL */
                    process(&greaterthan, &d_greaterthan, args_pipe,
                            &nargs_p, &fileno_out, &fileno_in, &lessthan,
                            &fout, &fin);
                    if (greaterthan || d_greaterthan)
                        err_remark("Redirection:\n"),
                        dup2(fileno_out, STDOUT_FILENO);
                }

                err_remark("close pipes\n");
                int close_pipes;
                for (close_pipes = 0; close_pipes < flag_count; close_pipes++)
                {
                    close(fd[close_pipes][0]);  /* JL */
                    close(fd[close_pipes][1]);  /* JL */
                }

                if (fout != stdout)
                    fclose(fout);
                if (fin != stdin)
                    fclose(fin);
                err_remark("execute command [%s]\n", args_pipe[0]);
                for (int i = 1; args_pipe[i] != NULL; i++)
                    err_remark("argument %d [%s]\n", i, args_pipe[i]);
                execvp(args_pipe[0], args_pipe);
                err_syserr("Failed to execute (i=%d) '%s': ", i, args_pipe[0]);
                /*NOTREACHED*/
            }// end child.
        }
        /* Parent process closes its copy of each pipe */
        for (i = 0; i < flag_count; i++)
        {
            close(fd[i][0]);
            close(fd[i][1]);
        }
        return;
    }
    else
        err_remark("No pipe in input - no command executed\n");
}

int main(int argc, char **argv)
{
    if (argc >= 0)
        err_setarg0(argv[0]);
    err_setlogopts(ERR_PID|ERR_MILLI);

    for ( ; ; )
    {
        printf("COP4338$ ");

        char cmdline[BUFSIZ];
        if (fgets(cmdline, BUFSIZ, stdin) == NULL)
        {
            printf("EOF\n");
            exit(1);
        }
        execute(cmdline);
        int status;
        int corpse;
        while ((corpse = wait(&status)) > 0)
            err_remark("PID %d exited with status 0x%.4X\n", corpse, status);
    }
}

process() 函数不需要区分参数列表中的 >>>;正确处理标准输出就足够了。调用代码会更简单。我不相信您应该使用 fopen() - 使用带有适当控制参数的 open() 会更明智。

但是,这至少看起来有效。源代码为shell61.c,编译为程序shell61

$ shell61
COP4338$ sort < shell61.c | grep main | cat > o.txt
shell61: 2019-05-04 22:17:39.982 - pid=8150: args[0] = [sort]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[1] = [<]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[2] = [shell61.c]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[3] = [|]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[4] = [grep]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[5] = [main]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[6] = [|]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[7] = [cat]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[8] = [>]
shell61: 2019-05-04 22:17:39.983 - pid=8150: args[9] = [o.txt]
shell61: 2019-05-04 22:17:39.983 - pid=8150: opened pipe - 3 and 4
shell61: 2019-05-04 22:17:39.983 - pid=8150: opened pipe - 5 and 6
shell61: 2019-05-04 22:17:39.984 - pid=8150: Parent launched child 8153
shell61: 2019-05-04 22:17:39.984 - pid=8150: Parent launched child 8154
shell61: 2019-05-04 22:17:39.984 - pid=8150: Parent launched child 8155
shell61: 2019-05-04 22:17:39.984 - pid=8154: child at work (i == 1)
shell61: 2019-05-04 22:17:39.984 - pid=8153: child at work (i == 0)
shell61: 2019-05-04 22:17:39.984 - pid=8155: child at work (i == 2)
shell61: 2019-05-04 22:17:39.985 - pid=8154: middle process in pipeline (i = 1, j = 7)
shell61: 2019-05-04 22:17:39.985 - pid=8155: final process in pipeline (i = 2, j = 11)
shell61: 2019-05-04 22:17:39.985 - pid=8153: first process in pipeline (i = 0, j = 4)
shell61: 2019-05-04 22:17:39.985 - pid=8154: close pipes
shell61: 2019-05-04 22:17:39.985 - pid=8155: -->> process():
shell61: 2019-05-04 22:17:39.985 - pid=8153: -->> process():
shell61: 2019-05-04 22:17:39.986 - pid=8154: execute command [grep]
shell61: 2019-05-04 22:17:39.986 - pid=8155: ---- process(): > o.txt
shell61: 2019-05-04 22:17:39.986 - pid=8153: ---- process(): < shell61.c
shell61: 2019-05-04 22:17:39.986 - pid=8154: argument 1 [main]
shell61: 2019-05-04 22:17:39.986 - pid=8155: <<-- process()
shell61: 2019-05-04 22:17:39.986 - pid=8153: <<-- process()
shell61: 2019-05-04 22:17:39.987 - pid=8155: Redirection:
shell61: 2019-05-04 22:17:39.987 - pid=8153: close pipes
shell61: 2019-05-04 22:17:39.987 - pid=8155: close pipes
shell61: 2019-05-04 22:17:39.987 - pid=8153: execute command [sort]
shell61: 2019-05-04 22:17:39.988 - pid=8155: execute command [cat]
shell61: 2019-05-04 22:17:39.993 - pid=8150: PID 8153 exited with status 0x0000
shell61: 2019-05-04 22:17:39.993 - pid=8150: PID 8154 exited with status 0x0000
shell61: 2019-05-04 22:17:39.994 - pid=8150: PID 8155 exited with status 0x0000
COP4338$ cat o.txt | cat
shell61: 2019-05-04 22:18:08.339 - pid=8150: args[0] = [cat]
shell61: 2019-05-04 22:18:08.339 - pid=8150: args[1] = [o.txt]
shell61: 2019-05-04 22:18:08.339 - pid=8150: args[2] = [|]
shell61: 2019-05-04 22:18:08.339 - pid=8150: args[3] = [cat]
shell61: 2019-05-04 22:18:08.339 - pid=8150: opened pipe - 3 and 4
shell61: 2019-05-04 22:18:08.340 - pid=8150: Parent launched child 8157
shell61: 2019-05-04 22:18:08.340 - pid=8150: Parent launched child 8158
shell61: 2019-05-04 22:18:08.340 - pid=8157: child at work (i == 0)
shell61: 2019-05-04 22:18:08.340 - pid=8158: child at work (i == 1)
shell61: 2019-05-04 22:18:08.340 - pid=8157: first process in pipeline (i = 0, j = 3)
shell61: 2019-05-04 22:18:08.341 - pid=8157: -->> process():
shell61: 2019-05-04 22:18:08.341 - pid=8158: final process in pipeline (i = 1, j = 5)
shell61: 2019-05-04 22:18:08.341 - pid=8157: <<-- process()
shell61: 2019-05-04 22:18:08.341 - pid=8158: -->> process():
shell61: 2019-05-04 22:18:08.342 - pid=8157: close pipes
shell61: 2019-05-04 22:18:08.342 - pid=8158: <<-- process()
shell61: 2019-05-04 22:18:08.342 - pid=8157: execute command [cat]
shell61: 2019-05-04 22:18:08.342 - pid=8158: close pipes
shell61: 2019-05-04 22:18:08.343 - pid=8157: argument 1 [o.txt]
shell61: 2019-05-04 22:18:08.343 - pid=8158: execute command [cat]
int main(int argc, char **argv)
shell61: 2019-05-04 22:18:08.347 - pid=8150: PID 8158 exited with status 0x0000
shell61: 2019-05-04 22:18:08.347 - pid=8150: PID 8157 exited with status 0x0000
COP4338$ ls
shell61: 2019-05-04 22:18:41.516 - pid=8150: args[0] = [ls]
shell61: 2019-05-04 22:18:41.516 - pid=8150: No pipe in input - no command executed
COP4338$ exit
$

当我首先添加 wait() 代码时,我收到如下消息:

$ shell61
COP4338$ ls | grep shell
shell61: 2019-05-04 14:29:23.201 - pid=5181: args[0] = [ls]
shell61: 2019-05-04 14:29:23.202 - pid=5181: args[1] = [|]
shell61: 2019-05-04 14:29:23.202 - pid=5181: args[2] = [grep]
shell61: 2019-05-04 14:29:23.202 - pid=5181: args[3] = [shell]
shell61: 2019-05-04 14:29:23.202 - pid=5181: opened pipe - 3 and 4
Process ID: 5182
Process ID: 5183
Process ID: 0
Process ID: 0
shell61: 2019-05-04 14:29:23.203 - pid=5183: child at work
PID 5183 exited with status 0x000B
shell61: 2019-05-04 14:29:23.203 - pid=5182: child at work
PID 5182 exited with status 0x000D
COP4338$ exit
$

5183 的退出状态是 0x000B,翻译过来就是“死于信号 11 — SIGSEGV”; 5182 的退出状态是 0x000D,它翻译为“死于信号 13 — SIGPIPE”。这是重要的信息。特别是通过 err_remark() 添加的打印有助于显示问题所在。发现您使用 &args_pipe[i] 而不是 &args_pipe[0]args_pipe 调用 process() 是 key 也是。

当跟踪看起来像:

$ shell61
COP4338$ ls | grep shell
shell61: 2019-05-04 16:24:24.297 - pid=6417: args[0] = [ls]
shell61: 2019-05-04 16:24:24.298 - pid=6417: args[1] = [|]
shell61: 2019-05-04 16:24:24.298 - pid=6417: args[2] = [grep]
shell61: 2019-05-04 16:24:24.298 - pid=6417: args[3] = [shell]
shell61: 2019-05-04 16:24:24.298 - pid=6417: opened pipe - 3 and 4
shell61: 2019-05-04 16:24:24.299 - pid=6417: Parent launched child 6419
shell61: 2019-05-04 16:24:24.299 - pid=6417: Parent launched child 6420
shell61: 2019-05-04 16:24:24.300 - pid=6420: child at work (i == 1)
shell61: 2019-05-04 16:24:24.299 - pid=6419: child at work (i == 0)
shell61: 2019-05-04 16:24:24.300 - pid=6420: final process in pipeline (i = 1, j = 5)
shell61: 2019-05-04 16:24:24.301 - pid=6419: first process in pipeline (i = 0, j = 2)
shell61: 2019-05-04 16:24:24.301 - pid=6420: -->> process():
shell61: 2019-05-04 16:24:24.302 - pid=6420: <<-- process()
greaterthan = 0
d_greaterthan = 0
shell61: 2019-05-04 16:24:24.302 - pid=6419: -->> process():
shell61: 2019-05-04 16:24:24.302 - pid=6420: close pipes
shell61: 2019-05-04 16:24:24.302 - pid=6419: <<-- process()
Lessthan = 0
shell61: 2019-05-04 16:24:24.303 - pid=6420: execute command [grep]
shell61: 2019-05-04 16:24:24.303 - pid=6420: argument 1 [shell]
shell61: 2019-05-04 16:24:24.303 - pid=6419: close pipes
shell61: 2019-05-04 16:24:24.304 - pid=6419: execute command [ls]
grep: (standard input): Bad file descriptor
PID 6420 exited with status 0x0100
PID 6419 exited with status 0x000D
COP4338$ exit
$

很明显,重定向存在问题 - 不清楚标准输入是否已关闭,或者 grep 是否被要求从只写文件描述符中读取;代码审查显示后者实际上是问题所在(在需要使用 fd[i][0] 的地方使用 fd[i][1])。

我无法充分强调拥有强大而简单的错误报告工具的帮助。我在大多数程序中使用 stderr.cstderr.h 代码 - 我很少不使用它们。您应该获取它们的副本或设计自己的等效版本,但请注意该代码经过 30 年的改进(尽管有些年我没有对其进行任何更改 - 2018 年是最近的一年) ,但在 1992-1995 年以及此后的其他年份中都没有改变)。我还保留着的最早版本是 1988 年的;代码实际上是在此之前启动的,但是我在移 Action 业时未能成功传输数据(事实证明8英寸软盘是一个糟糕的选择)。

关于c - C 的管道问题。是否有额外的进程正在执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55931016/

相关文章:

c++ - 如何创建仅在您的计算机上可访问的命名管道? (VS08 C++)

c - c 中的管道消息被截断

c - sigsuspend 等价于 sigprocmask、pause、sigprocmask 的原子系列?

python - 如何从多个 python-flask 子进程中收集 prometheus 指标?

c - Little Endian 上的 Mersenne Twister

c - 如何确定 union 中使用的是什么类型?

c - 使用 exec 程序从父级读取和写入多个子级

c - 如何在C中将文件中每一行的首字母设为大写

c - 这条语句背后的逻辑是什么: for (--index; index >= 0; --index)?

c++ - 多个进程将元素推送到列表 STL C++