簡體   English   中英

基本Shell程序的管道問題

[英]Problems with piping for basic shell program

我已將其與以前涉及管道的帖子進行了比較,但似乎找不到問題。 父母中的一切似乎都應該關閉。 當我輸入有效命令(例如“ ls | grep a”)時,它可以正常工作,但是如果它不是有效命令(例如“ ls | grep 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);
        }
 }

這是我程序中用於管道的函數:

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);
}

您的問題是一對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仍在運行的后台進程時不掛起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM