在Linux編程中,咱們常常使用 Fork()
。然而很多狀況下,fork
是有危險的。可是又不能簡單使用vfork
替換就成了。這個筆記說明了二者使用的一些注意點。
本文地址:https://segmentfault.com/a/11...html
fork與vfork的區別
vfork,fork,exec函數的區別
C語言函數 atexit execl execlp ……(太長了)編程
pid_t vfork(void);
函數vfork
的做用是建立一個子進程,而這個子進程的做用是用於調用exec()
,從而再執行一個新進程(每每是用來執行其它的程序)segmentfault
在程序的執行效果上,fork
會將父進程的地址空間複製一份,,可是vfork
並非這麼作,而是 vfork 以後的子進程,在調用 exec 或 exit 以前,在父進程的空間中執行。函數
vfork
保證子進程優先執行到exec
或exit
以前,父進程都不會被調度。fork
父子進程執行順序不肯定。.net
所以,執行了vfork
以後,子進程請當即執行 exec,而不要再執行一次 fork,不然就可能致使死鎖。
或者這麼說,若是在exec
或exit
以前依賴於父進程的進一步動做,就會致使死鎖code
另外請留意,exec
並非建立進程,只是用新程序替換了當前進程的上下文。orm
頻繁調用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