用C发出管道问题。是否可以执行额外的过程?

时间:2019-05-01 02:39:55

标签: 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 $:像应该这样。出现未定义的行为。我对为什么会这样的猜测是因为第4个进程还在继续,因此像父进程一样回到了main(),但是我无法查明为什么还要创建它。

当我尝试运行ls -l | cat > o.txt

时,也会出现未定义的行为

这是GDB的输出:

至于要解决此问题,我还不确定是否是导致此问题的原因。我尝试使用gdb调试器通过键入“ set follow-fork-mode child”并在第3个子进程的第1行使用断点来调试第3个子进程,但没有任何反应。这样只能调试第一个子进程。

/* 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()扫描构成命令的一串参数,并根据程序看到的符号设置标志。

1 个答案:

答案 0 :(得分:0)

您的代码有很多问题:

  • 没有呼叫wait()或等效电话。
  • 将管道的错误端连接到标准输入或标准输出。
  • 访问参数集的错误部分-命令名称和参数。
  • 为管道关闭错误的文件描述符,可能会反复发生。

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

我需要添加诊断信息以找出您的代码在做什么错。因此,我使用了错误报告代码,该代码在GitHub上的SOQ(堆栈溢出问题)存储库中以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()添加的印刷有助于显示出问题所在。同样重要的是,发现您使用process()而不是&args_pipe[i]&args_pipe[0]来呼叫args_pipe

跟踪显示如下:

$ 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][1],其中需要使用fd[i][0])。

我不能太强调拥有功能强大而简单的错误报告工具将如何提供帮助。我在大多数程序中都使用stderr.cstderr.h代码-在极端情况下,我很少使用它们。您应该获取它们的副本或设计自己的副本,但要注意该代码已有30年的完善(尽管有些年我没有对其进行任何更改-2018年是最近的一年) ,但在1992年至1995年并没有改变,此后的其他年份也没有变化。我仍然拥有的最早版本是1988年。该代码实际上是在此之前启动的,但是在移动作业时我未能成功传输数据(事实证明,这是一个错误的选择)(8英寸软盘)。