fork:用于创建进程,进程创建成功时,子进程返回0;创建失败时,返回-1;父进程返回子进程的id号 fork:除了进程的id号不同,父子进程的内容一样,执行顺序不同;一般情况要满足僵进程,借助wait()或者waitpid()函数 vfork:由于父进程主要是为了创建子进程,若用fork创建时,会造成资源的浪费;因此,fork应用而生。 vfork:父子进程,共享内存空间,vfork调用exec家族或exit函数满足子进程先执行。
Child i=10; Parent i=100; 执行的路线不同,i的值不同
1 #include<stdio.h> 2 #include<unistd.h> 3 #include<stdlib.h> 4 int main() 5 { 6 int i=100; //创建进程,数据共享 7 pid_t pid=vfork(); 8 if(pid == 0) 9 { 10 i=10; 11 printf("Child i=%d\n",i); 12 exit(0); 13 } 14 else if(pid > 0) 15 { 16 printf("Parent i=%d\n",i); 17 } 18 else 19 { 20 perror("fork"); 21 }Child i=10 Parent i=10,父进程等待子进程结束后执行,并且父进程和子进程共享内存空间
wait:父进程等待自己的一个直系的、提前执行的子进程,返回等待进程的id号
#include<stdio.h> #include<sys/wait.h> #include<unistd.h> int main() { pid_t pid = fork(); if(pid>0) { pid = fork(); // 0 号进程 if(pid>0) { printf("This is 0=[%d]\n",getpid()); int status; pid_t wait_res=wait(&status); printf("wait_res = %d\n",wait_res); if(IFEXITED(status)) { printf(" Child is ok finish.\n"); } else printf("Child is error finish.\n"); } //2 号进程 else if(pid == 0) { sleep(2); printf("This is 2=[%d]\n",getpid()); } } else if(pid == 0) { pid = fork(); //1号进程 if(pid>0) { sleep(5); printf("This is 1=[%d]\n,getpid()"); } //号进程 else if(pid==0) { printf("This is 3=[%d]\n",getpid()); } } else { perror("fork"); } return 0; }进程之间的关系:
结果:
分析:父进程等待直系子进程,1号和2号进程,1号进程休眠5s,2号进程休眠1s,因此等待的是2号进程。因此,wait函数返回2号进程的id号
waitpid:父进程等待自己的一个直系的、指定的一个子进程,返回等待的进程的id号
#include<stdio.h> #include<sys/wait.h> #include<unistd.h> int main() { pid_t pid = fork(); if(pid>0) { //子进程的id号 pid_t g_pid = pid; pid = fork(); // 0 号进程 if(pid>0) { printf("This is 0=[%d]\n",getpid()); int status; pid_t wait_res=waitpid(,g_pid,&status,); printf("wait_res = %d\n",wait_res); if(IFEXITED(status)) { printf(" Child is ok finish.\n"); } else printf("Child is error finish.\n"); } //2 号进程 else if(pid == 0) { sleep(2); printf("This is 2=[%d]\n",getpid()); } } else if(pid == 0) { pid = fork(); //1号进程 if(pid>0) { sleep(5); printf("This is 1=[%d]\n,getpid()"); } //号进程 else if(pid==0) { printf("This is 3=[%d]\n",getpid()); } } else { perror("fork"); } return 0; }分析:即使等待的2号进程时间长,1号进程时间短;但由于是指定等待了2号进程,返回2进程的id.
在 函数 execl, execlp, 和 execle 中, const char *arg 以及 省略号 代表 的 参数 可被 视为 arg0, arg1, …, argn.,他们 合起来描述了 指向 null 结尾的 字符串 的 指针 列表, 即 执行程序 的 参数列表. 作为 约定, 第一个 arg 参数应该 指向 执行程序名自身. 参数列表 必须 用 NULL 指针 结束!
链表形式
//路径名 自身
int execl( const char *path, const char *arg, ...); int execlp( const char *file, const char *arg, ...); int execle( const char *path, const char *arg , ..., char * const envp[]);ls
//不带环境变量 execl("/bin/ls",ls,NULL); //带有环境变量 path execlp("ls",ls,NULL);数组形式
//路径名 自身
int execv( const char *path, char *const argv[]); int execvp( const char *file, char *const argv[]);ls
//不带path char *envp[]={"ls",NULL}; execv("/bin/ls",envp); //带 path char *envp[]={"ls",NULL}; execlp("ls",envp);1、fork、vfork都可以创建进程,调用一次返回两次 2、fork要使用wait、waitpid,达到僵进程 3、vfork父子进程共享内存创建进程,exit()函数保证子进程先执行;exec家族处理问题 4、exec家族函数,在子进程中执行其他的操作
