0

与えられたパスのリストからコマンドを見つけてコマンドを実行する、コースの宿題用の基本的なシェルを書いています。また、パイプを処理するためのものです。ただし、子プロセスをforkすると、gdbに「書き込みエラー:パイプが壊れています」というメッセージが表示され、プログラムが突然終了します。

正しいパイプの開閉に注意を払っていたので、なぜこれが起こっているのか理解できないようです。プロセスのフォークは希望どおりに機能しているようです。CおよびUNIXプログラミングの経験が豊富な人が問題の診断を手伝ってくれませんか?私のフォークの実装/パイプの実装に論理的に間違っているものはありますか?

//commands is of the format {"ls -al", "more", NULL}
//it represents commands connected by pipes, ex. ls -al | more
char **commands = parseArgv(consoleinput, SPECIAL_CHARS[4]);

int numcommands = 0;

while( commands[numcommands]!=NULL )
{
    numcommands++;
}

const int  numpipes = 2*(numcommands-1);

int pipefds[numpipes];

int i=0;
for(i=0; i<numpipes;i=i+2)
{
    pipe(pipefds+i);
}

int pipe_w = 1;
int pipe_r = pipe_w - 3;
int curcommand = 0;

while(curcommand < numcommands)
{
    if(pipe_w < numpipes)
    {
        //open write end
        dup2(pipefds[pipe_w], 1);
    }

    if(pipe_r > 0)
    {
        //open read end
        dup2(pipefds[pipe_r], 0);
    }

    for(i=0;i<numpipes;i++) //close off all pipes
    {
        close(pipefds[i]);
    }

    //Parse current command and Arguments into format needed by execv

    char **argv = parseArgv(commands[curcommand], SPECIAL_CHARS[0]);

    //findpath() replaces argv[0], i.e. command name by its full path ex. ls by /bin/ls
    if(findPath(argv) == 0)
    {
        int child_pid = fork();

        //Program crashes after this point
        //Reason: /bin/ls: write error, broken pipe

        if(child_pid < 0)
        {
            perror("fork error:");
        }
        else if(child_pid == 0)     //fork success
        {
            if(execv(argv[0], argv) == -1)
            {
                perror("Bad command or filename:");
            }

        }
        else
        {
            int child_status;
            child_pid = waitpid(child_pid, &child_status, 0);
            if(child_pid < 0)
            {
                perror("waitpid error:");
            }
        }
    }
    else
    {
        printf("Bad command or filename");
    }
    free(argv);

    curcommand++;
    pipe_w = pipe_w + 2;
    pipe_r = pipe_r + 2;
}

//int i=0;
for(i=0;i<numpipes;i++) //close off all pipes
{
    close(pipefds[i]);
}

free(commands);
4

1 に答える 1

0

fork() 呼び出しの後、つまり子プロセスでファイル記述子を複製するのが正しい方法です。また、waitpid() 呼び出しにより、一方の子プロセスが他方のプロセスを待機し、シェルがハングします。wait() 呼び出しはループの後に移動する必要があります。つまり、親はすべての子を待機する必要があります。

于 2013-02-11T20:51:02.013 に答える