基本shell程序的管道问题

时间:2014-01-29 23:25:49

标签: c linux shell lex

我将此与之前涉及管道的帖子相比较,我似乎无法找到问题。父母的一切似乎都应该关闭。当我输入一个有效的命令(ex“ls | grep a)但它不是一个有效的命令(ex”ls | grup a)时,程序会停止响应用户输入(它继续运行,但它只是没有“)当你输入一个命令时做任何事情)

主要功能:

int main() {
int i;
char **args; 

int pipeCheck = 0;
int argCount = -1;
int blank = 0;

while(1) {
    args = getln();

    if (args[0] != NULL){
        blank = 1;
        if (strcmp(args[0],"exit")==0) exit(0);
    }
    for(i = 0; args[i] != NULL; i++) {
    if (strcmp(args[i], "|")==0){
            pipeCheck = i;
        }
   }
   if (pipeCheck != 0){
            args[pipeCheck] = NULL;
            directPipe(args, pipeCheck, argCount, ampCheck);
        }
 }

} 这是我的程序中的管道功能:<​​/ p>

int directPipe(char ** args, int fileNumber, int argCount,int ampCheck){
    int fd[2];
    int child1,child2;
    int status;
    int i;
    char * piped[10000];
    int count = 0;

    for (i = (fileNumber+1); args[i] != NULL; i++){
        piped[count] = args[i];
        count++;
    }
    piped[count] = NULL;

    printf("\nPipe attempted...\n");

    pipe(fd);

    child1 = fork();
    if (child1==0){
        close(1);
        dup(fd[1]);
        close(fd[0]);
        close(fd[1]);

        execvp(args[0], args);
        printf("Unknown command, please try again.");
        exit(0);
    }

    child2 = fork();

    if (child2 ==0){

        close(0);
        close(fd[1]);
        dup(fd[0]);
        close(fd[0]);

        execvp(piped[0], piped);
        printf("Unknown command, please try again.");
        exit(0);
    }

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

    if (ampCheck == 0){
        while (wait(&status) != child1);
        while (wait(&status) != child2);
    }
    else{
        printf("\nampCheck = %d",ampCheck);
        sigset(child2, printer());
    }

    return (0);
}

1 个答案:

答案 0 :(得分:0)

你的问题是wait()循环对:

while (wait(&status) != child1);
while (wait(&status) != child2);

在你的场景中,第二个孩子在第一个孩子出现之前死亡,所以你在第一个循环中收集它的尸体,但忽略它。然后第二个循环进入忙碌的等待状态,因为不再有孩子了。

至少,您需要:

int corpse;

while ((corpse = wait(&status)) != -1 && corpse != child1 && corpse != child2)
    ;
while ((corpse = wait(&status)) != -1 && corpse != child1 && corpse != child2)
    ;

这可以处理以任何顺序死亡的儿童 - 但只有两个孩子。对于更通用的管道(三个或更多进程),您必须更加努力 - 并使用单个循环。更一般的形式将是:

int corpse;

while ((corpse = wait(&status)) != -1)
{
    if (record_death_of_child(corpse, status) == -1)
        break;
}

您的流程创建代码记录所创建流程的PID,record_death_of_child()代码处理该PIDS列表,并且当当前管道中没有更多子代值时返回-1(和0)除此以外)。或者你可以让它使用其他一些启发式来确定何时退出循环。请注意,如果您在后台运行长时间的作业,则其中任何一个都可能死亡,并且该循环将收集该尸体。 “记录死亡”功能也需要处理这样的过程 - 例如,它们不能再被带到前台,你需要报告它们已经退出等等。

您也可能最终使用waitpid(),因为您可以安排在WNOHANG仍在运行的后台进程时不挂起。