簡體   English   中英

Printf和fork:即使使用wait(NULL)時,順序也錯誤

[英]Printf and fork: wrong ordering, even when wait(NULL) is used

因此,我正在創建一個非常簡單的外殼包裝程序。 主進程使用readline讀取一行,然后將其解析為char * [],然后由execvp處理。 Fork用於確保execvp運行后程序繼續運行。 如果命令以&結尾,則母進程在繼續之前不會等待派生完成。 如果結尾沒有&,則母親等待孩子完成。

一些代碼:主要和接受輸入功能

int main(){
    //Welcome message
    printf("Welcome to Bourne Shell Wrapper! Enter commands to run them, use ctrl+d to exit\n");
    while(1){
        //Prefering the complex readline over the easier scanf because of many functions that scanf does not offer.
        char* line = readline("shw> ");
        if (line == NULL) return 0;
        struct Command command = parseInput(line);
        if (command.params != NULL){
            if (!runCommand(command)) return 1;
        }
    }

結構命令:

struct Command{
    char async;
    char** params;
};

運行命令的函數:

int runCommand(struct Command command){
    //Fork, let the child run the command and the parent wait for the child to finish before returning
    //The child has 0 as childPid, the mother has another positive value. Thats how we seperate them
    pid_t childPid = fork();
    if (childPid == -1){
        printf("Failed to create child\n");
        return 0;
    } else if (childPid == 0){
        if (execvp(command.params[0], command.params) == -1){
            fprintf(stderr,"%s: ",strerror(errno));
            printCommand(command);
        }
        return 1;
    } else {
        if (!command.async){
            //This way the mother will wait until all her childeren are done before continuing 
            wait(NULL);
        } else {
        }
        return 1;
    }
}

所以,這就是問題所在。 當您不想異步時,這些東西就可以了:

Welcome to Bourne Shell Wrapper! Enter commands to run them, use ctrl+d to exit
shw> ls
debug  Makefile  obj  release  rpi-release  src
shw>

正如預期的那樣:母進程等待直到子進程返回,然后再次打印。 然后:

shw> ls &
shw> debug  Makefile  obj  release  rpi-release  src

半預期的:由於父級繼續運行而無需等待該過程,因此在ls輸出之前會打印shw。 但是之后:

ls
shw> debug  Makefile  obj  release  rpi-release  src

奇怪的! 父級應該等到子進程完成后才能重新打印shw>,但是它會在子級之前打印。

我不知道為什么會這樣。 有人可以指出我正確的方向嗎? 作為記錄,無需使用&,一切正常。

您的評論說:

the mother will wait until all her childeren are done before continuing

但這不是事實。 wait()等待一個孩子,無論哪個孩子先完成(包括一個在wait()調用之前完成的孩子wait()

總結一下:執行異步命令時,您不必等待子進程完成; 當執行同步命令時,您等待一個孩子完成。 總而言之,您的wait()少於創建的子級。

當您調用wait() ,您知道您正在等待一個特定的孩子,但是您沒有告訴您wait它,因此它將只等待第一個完成的孩子。 最終等待的孩子可能是先前發起的異步孩子,該孩子已經完成但狀態尚未獲得。

因此,這里有一個重要原則: 每個孩子都必須在某個時候獲得收成。 如果您wait(2)每個孩子wait(2) ,您將積累僵屍進程:實際上已經死了但仍在OS進程列表中的進程,因為它們的狀態尚未恢復。

暫無
暫無

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

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