在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