2015-05-08 26 views
0

我在嘗試將fork()和exit()函數用於課程作業時遇到了一個問題。問題是我的子進程在錯誤結束時結束。這裏是我的代碼:子進程在出錯時終止

int main(int argc, char** argv) 
{ 
    int shmid; 
    int *shmptr; 
    int N = 10; 

    // Create shared memory segment 
    if ((shmid = shmget(IPC_PRIVATE, N * N * sizeof(int), 0600)) < 0) 
    { 
     puts("parent: shmget error"); 
     return -1; 
    } 

    // Attach shared memory segment 
    if ((shmptr = shmat(shmid, 0, 0)) == (void *) -1) 
    { 
     puts("parent: shmat error"); 
     return -1; 
    } 

    int ret = fork(); 
    if (ret == 0) 
    { 
     int status = 0; 
     if (wait(&status) == -1) 
     { 
      puts("parent: Child terminated on error."); 
     } 
     else 
     { 
      printf("parent: status of child: %d\n", status); 
     } 
     puts("parent: End parent.");   
    } 
    else 
    { 
     puts("child: End child."); 
     _exit(0); 
    } 

    exit(0); 
} 

我總是得到兒童終止對錯誤警告。有什麼建議麼?

回答

1

您的診斷「兒童在錯誤時終止」是生成它的條件的錯誤表徵。如果有錯誤,wait()函數返回-1;如果調用進程沒有孩子等待或者函數被信號中斷,就會發生這種情況。

在你的情況下,原因是前者。當它成功時,fork()函數在子進程中返回0,並且它在父進程中返回新的子進程ID(大於0的數字)。除此之外,這是父母和孩子如何區分哪個是哪個。您在孩子中調用wait(),該孩子沒有自己的子進程。

請注意,這是潛在的問題,爲孩子打電話_exit()而不是exit(),因爲前者會突然停止的孩子(不沖洗打開的文件,除其他事項外),也將導致母公司將信號(與SIGCHILD )。這偶爾是你想要的,但我不明白爲什麼你會想要它在這種情況下。

還請注意,wait()提供的狀態會對收集的過程的若干單獨詳細信息進行編碼,包括但不限於其退出代碼。除了通過爲此目的提供的各種宏提取感興趣的部分之外,對整個狀態進行任何操作通常都沒有用處。例如,要獲取孩子的退出代碼,您應該將狀態傳遞給WEXITSTATUS()宏。在真實的代碼中,測試過程是否正常退出可能是明智的,而不是由於信號而終止。宏可以從狀態中提取該信息。還有其他編碼信息,以及用於提取它的其他宏。

int pid = fork(); 
    if (pid == 0) 
    { 
     /* child */ 
     puts("child: End child.\n"); 
     exit(0); 
    } 
    else if (pid > 0) 
    { 
     /* parent */ 
     int status = 0; 
     if (wait(&status) == -1) 
     { 
      puts("parent: failed to wait.\n"); 
     } 
     else 
     { 
      printf("parent: child's exit code: %d\n", WEXITSTATUS(status)); 
     } 
     puts("parent: End parent.\n");   
    } 
    else 
    { 
     /* parent; error */ 
     puts("failed to fork.\n"); 
    } 

因此,你可能會像這樣做的更好

0

ret應在子進程內部爲0。在父進程中,ret應該包含孩子的PID

int ret = fork(); 
if (ret < 0) { perror("fork"); exit(1); } /* handle fork error */ 
if (ret == 0) 
{ 
    puts("child: End child."); 
    _exit(0); 
} 
else 
{ 
    /* <wait> code goes here */ 
}