fork 和 vfork 使用的注意事項和 system() 函數的替代

在Linux編程中,咱們常常使用 Fork()。然而很多狀況下,fork是有危險的。可是又不能簡單使用vfork替換就成了。這個筆記說明了二者使用的一些注意點。
本文地址:https://segmentfault.com/a/11...html


Reference:

fork與vfork的區別
vfork,fork,exec函數的區別
C語言函數 atexit execl execlp ……(太長了)編程

vfork() 與 fork()

pid_t vfork(void);

vfork的做用

函數vfork的做用是建立一個子進程,而這個子進程的做用是用於調用exec(),從而再執行一個新進程(每每是用來執行其它的程序)segmentfault

代碼空間

在程序的執行效果上,fork會將父進程的地址空間複製一份,,可是vfork並非這麼作,而是 vfork 以後的子進程,在調用 exec 或 exit 以前,在父進程的空間中執行函數

執行順序

vfork保證子進程優先執行到execexit以前,父進程都不會被調度。
fork父子進程執行順序不肯定。.net

所以,執行了vfork以後,子進程請當即執行 exec,而不要再執行一次 fork,不然就可能致使死鎖。
或者這麼說,若是在execexit以前依賴於父進程的進一步動做,就會致使死鎖code

另外請留意,exec並非建立進程,只是用新程序替換了當前進程的上下文。orm

system()的替代

頻繁調用system()以後,有可能卡死不返回,就是由於出現了這個狀況。system是基於fork實現的,調用後父子進程調用順序不必定,可能致使system()調用死鎖。
這個危險的函數,如今咱們已經禁用了。換成使用vfork或者是__libc_fork實現,代碼以下(這份是我本身寫的,不是公司的代碼,不過原理上差很少):htm

#define _CMD_LEN    (256)

static int _system (char *cmd);
int AMCSystemCmd (const char *format, ...)
{
    char cmdBuff[_CMD_LEN];
    va_list vaList;
    
    va_start (vaList, format);
    vsnprintf ((char *)cmdBuff, sizeof(cmdBuff), format, vaList);
    va_end (vaList);
    
    return _system ((char *)cmdBuff);
}
extern int __libc_fork (void);
static int _system (char *command)
{
    int pid = 0;
    int status = 0;
    char *argv[4];
    extern char **environ;
    
    if (NULL == command) {
        return -1;
    }
    
    pid = __libc_fork();        /* vfork() also works */
    if (pid < 0) {
        return -1;
    }
    if (0 == pid) {             /* child process */
        _close_all_fds();       /* 這是我本身寫的一個函數,用來關閉全部繼承的文件描述符。可不用 */
        argv[0] = "sh";
        argv[1] = "-c";
        argv[2] = command;
        argv[3] = NULL;
        
        execve ("/bin/sh", argv, environ);    /* execve() also an implementation of exec() */
        exit (127);
    }
    
    // else
    /* wait for child process to start */
    do
    {
        if (waitpid (pid, &status, 0) < 0) {
            if (errno != EINTR) {
                return -1;
            }
            else {
                return status;
            }
        }
    } while (1);
    
    return 0;
}

使用時用AMCSystemCmd()直接替代system便可,還支持動態參數列表呢blog

相關文章
相關標籤/搜索