2014-03-12 113 views
2

我用fork()來創建子進程。從子進程中我使用exec()來啓動新進程。我的代碼如下:C/C++ linux fork()和exec()

...... 
    pid = fork(); 
    if (pid > 0) { 
     WriteLog("Parent Process"); 
     //Do something 
    } else if (pid == 0) { 
     WriteLog("Child process"); 
     int return = execl(ShellScript); 
     if (return == -1) 
      WriteLog("Launch process fail"); 
    } else { 
     WriteLog("Can't create child process"); 
    } 
    ...... 

注意:WriteLog函數將打開文件,寫入日誌和關閉文件。 (它被刷新) ShellScript將啓動新的進程c/C++。

我長時間運行我的程序,上面的代碼被調用很多次。有時(很少)有問題發生,雖然子進程已成功創建(我仔細檢查過),但新進程無法啓動成功。有一件事情是極端的誤解,當這個問題發生時,儘管子進程被創建成功,但「子進程」日誌不能被打印。

在正常情況下(沒有錯誤發生),打印「子進程」和「父進程」日誌的次數相同。

在異常情況下,雖然子進程始終創建成功,但它們並不相同。在此情況下,「啓動進程失敗」和「無法創建子進程」日誌不會被打印。 請幫我諮詢。

回答

4

請記住stdio(3)已被緩衝。在fork之前總是打電話fflush(NULL);(詳見fflush(3))。在每個printf(3)格式字符串末尾添加一個\n(換行符)(或者,按照fflush(NULL); ...的順序)。

函數execl(3)(也許你想要execlp?)可能會失敗(因此設置errno失敗)。

} else if (pid == 0) { 
    printf("Child process\n"); 
    fflush(NULL); 
    execl("/bin/foo", "foo", "arg1", NULL); 
    // if we are here execl has failed 
    perror("Launch process fail"); 
} 

上的錯誤,fork(2)未能通過返回-1,並將errno(3)(見perror(3)strerror(3))。所以,你的最後else應該

} else { 
    perror("Can't create child process"); 
    fflush(NULL); 
} 

您可能需要使用strace(1)(尤其是作爲strace -f yourprog ...)瞭解有關syscalls(見syscalls(2) ...)

WriteLog應該使用strerrorerrno值保存在開始WriteLog ....)。我建議像

void WriteLog(const char* msg) { 
    int e = errno; 
    if (e) 
    syslog (LOG_ERR, "%s [%s]", msg, strerrno(e)); 
    else 
    syslog (LOG_ERR, "%s", msg); 
} 

請參閱syslog(3)

fork-ed過程的數量有限制,請參見setrlimit(2)RLIMIT_NPROC和內置的bash ulimit

也請參閱Advanced Linux Programming

+0

我很抱歉我的代碼不清楚。我剛剛更新。我曾經想過每次寫日誌時我都會沖洗。所以我用文件寫日誌。並且當子進程創建成功時,啓動進程失敗時日誌仍不會打印。 (我根據kill(childid)函數檢查這個東西 – bm2i

+0

我會嘗試使用strerror和errno。目前我的系統也使用syslog和log文件來打印日誌,我會嘗試使用它。謝謝你一個好主意。 – bm2i

+0

同時分叉進程總是小於7.所以我認爲它沒有超過限制 – bm2i