vfork和exec系列函数创建进程
#include <sys/types.h> #include <unistd.h> pid_t vfork(void); 功能:创建一个子进程,返回值特点与fork没有区别
vfork的特点:
-
当调用vfork系统调用时,父进程会进入阻塞状态,子进程一定先返回执行
-
子进程返回时,先临时使用父进程的相关资源,然后等待exec系列函数执行加载一个可执行文件,从而让子进程去启动另一个程序,把那个程序的资源替换自己原来的资源。
-
当子进程调用完exec系列函数,替换完原来的所有资源后,子进程才算真正创建完毕,此时父进程才会接触阻塞状态,返回子进程的pid
-
如果子进程不调用exec系列函数后果:
-
情况1:子进程一直没有创建成功,导致父进程一直处于阻塞状态,无法返回
-
情况2:子进程直接结束并释放相关资源,此时子进程使用的还是父进程的资源,父进程会返回,但会产生段错误,因为它的相关资源已经被子进程错误释放掉了
-
-
vfork不能单独创建出子进程,必须与exec系列函数中某个函数配合使用
fork和vfork的区别:
-
vfork调用后,子进程先返回,而fork调用,谁先返回不确定
-
vfork不会复制、共享父进程的相关资源,而是去加载其他程序,替换原来的临时资源
-
以exec系列函数创建的子进程不会继承父进程的信号处理方式,但是可以继承父进程的信号屏蔽
exec系列函数:
功能:都是为了与vfork配额创建子进程的函数 int execl(const char *path, const char *arg, ... /* (char *) NULL */); path:要加载的程序的路径 arg:命令行参数,最起码第一个是执行可执行文件的命令,最后一个以NULL结尾 int execlp(const char *file, const char *arg, ... /* (char *) NULL */); file:只需要被加载程序的文件名,系统会根据环境变量PATH中的路径去查找该文件 int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */); envp:环境变量表,相当于父进程把自己的环境变量表拷贝给子进程 int execv(const char *path, char *const argv[]); argv:把命令行参数以字符串指针数组方式提供,注意:一定要以NULL结尾 int execvp(const char *file, char *const argv[]); int execvpe(const char *file, char *const argv[], char *const envp[]);
#include <stdio.h> #include <unistd.h> int main(int argc,const char* argv[]) { pid_t pid = vfork(); if(0 == pid) { printf("我是子进程%u\n",getpid()); // 加载其他程序 //execl("hello","hello","xixi","10",NULL); char* a[] ={"hello","hehe","xx",NULL}; execv("hello",a); printf("-------------\n"); } else { printf("我是父进程%u\n",getpid()); } printf("************\n"); }