赞
踩
#include<unistd.h>
#include<sys/types.h>
函数原型
pid_t fork( void);
(pid_t 是一个宏定义,其实质是int 被定义在#includesys/types.h>中)
返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
fork系统调用用于创建一个新进程,称为子进程,它与父进程 同时运行(并发),且运行顺序不定(异步)。
fork()函数如果成功调用一次返回两个值,一共可能有三种不同的返回值:(1)在父进程中,fork返回新创建子进程的进程ID;
(2)在子进程中,fork返回0;
(3)如果出现错误,fork返回一个负值。
#include<stdio.h> #include<unistd.h> #include<sys/types.h> int main() { pid_t child; child = fork(); if(child == 0)//子进程抢到处理机资源并运行 {//子进程运行代码 for(int i = 0; i < 3; i++) { printf("I am child!\n"); sleep(1); } } else if(child > 0)//父进程抢到处理机资源并运行 {//父进程运行代码 for(int i = 0; i < 3; i++) { printf("I am parent!\n"); sleep(1); } } return 0; }
父进程与子进程并发运行,且运行顺序不一定(可以调整循环次数观察结果)
#include<stdio.h> #include<unistd.h> #include<sys/types.h> int main() { pid_t child1, child2; child1 = fork(); //执行到这段代码时,子进程同时开始和父进程一起向下执行 child2 = fork(); //该段代码被父进程和子进程(child1)同时执行,即子进程多创建了一个进程 if(child1 == 0) {//因为子进程(child1)会还会创建一个子进程(孙进程), 故这段代码会被执行两次 printf("I am child1!\n"); } else if(child1 > 0) { if(child2 == 0) { printf("I am child2!\n"); } else if(child2 > 0) { printf("I am parent!\n"); } } return 0; }
因为子进程(child1)下已经创建了一个子进程(孙进程),当子进程(child1)抢到处理机资源后
从父进程(child1)和子进程(孙进程)的角度来推导,父进程(child1)就会和它的子进程同时执行进程(child1)的代码段
#include<stdio.h> #include<unistd.h> #include<sys/types.h> int main() { int i, n; pid_t child; printf("请输入需要创建的子进程个数:"); scanf("%d", &n); for(i = 0; i < n; i++) { child = fork(); if(child == 0) //如果子进程抢到处理机后就退出循环,不然子进程的循环下还会i个创建进程 break; //若不退出,最终加上父进程一共有2^n个进程 } //循环创建完子进程后,(i+1)值对应着每个子进程 if(i < n) { printf("I am %d child!(pid = %d)\n", i+1, getpid()); } else { printf("I am parent!\n"); } return 0; }
#include<sys/types.h>
#include<sys/wait.h>
函数原型:pid_t wait(int *status);
返回值:
成功:返回结束的子进程pid,终止回收子进程,
失败:返回-1(没有子进程)失败原因存于errno 中
参数:
(1)wait()会暂时停止目前进程的执行, 即阻塞父进程,等待子进程结束或者其他信号.
(2)如果在调用wait()时子进程已经结束, 则wait()会立即返回子进程结束状态值.
(3)子进程的结束状态值会由参数status返回, 而子进程的进程识别码也会一并返回.
(4)如果不考虑结束状态值, 则参数 status 可以设成NULL.
函数原型:pid_t waitpid(pid_t pid, int *status, int options); 返回值: 正常:返回已成功结束运行的子进程的进程号 使用选项WNOHANG且没有子进程退出:0 失败:-1 参数 (1)pid: pid > 0|只等待进程ID等于pid的子进程,不管其他子进程是否结束,只要指定子进程未结束,waitpid()就会一直等下去 pid =-1|等待任何一个子进程退出,此时和wait()作用一样 pid = 0|等待其组ID等于调用进程的组ID的任一子进程 pid <-1|等待其组ID等于pid的绝对值的任一子程序 (2)options: WNOHANG:若pid指定的子进程未结束,则waitpid()不阻塞父进程,立即返回0; WUNTRACED:若pid指定进程已被暂停,且其状态自暂停以来还未报告过,则返回其状态 0:同wait(),阻塞父进程,等待子进程退出 (3)stasus: 同wait
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> int main() { int status; pid_t child1, child2, parent; printf("parent(pid = %d, ppid = %d\n", getpid(), getppid()); if((child1 = fork()) == 0)//子进程child1抢到处理机资源并运行 {//子进程child1运行代码 for(int i = 1; i <= 10; i++) { printf("child1(进度 = %d%) is working!(pid = %d,ppid = %d)\n",i * 10, getpid(), getppid()); sleep(1); } printf("Child1 had completed!\n"); } else if(child1 > 0)//返回到父进程时还需要判断子进程child2是否抢到资源 { if((child2 = fork()) == 0)//子进程child2抢到处理机资源并运行 {//子进程child2运行代码 for(int i = 1; i <= 10; i++) { printf("child2(进度 = %d%) is working!(pid = %d,ppid = %d)\n",i * 10, getpid(), getppid()); sleep(1); } printf("Child2 had completed!\n"); } else if(child2 > 0)//父进程parent抢到处理机资源并运行 { printf("The last child's pid = %d\n", wait(&status)); for(int i = 1; i <= 3; i++) { printf("parent(进度 = %d%) is working(pid = %d ppid = %d)\n", i * 10, getpid(), getppid()); sleep(1); } printf("Parent had Complete!\n"); } else if(child2 == -1) { printf("Error!\n"); } } else { printf("Error!\n"); } return 0; }
如下运行结果可以证明进程的并发性和异步性,进程之间并发运行,且运行的顺序不定
wait()会阻塞父进程,等待子进程全部结束后,父进程才开始运行
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> int main() { int status; pid_t child1, child2, parent; printf("parent(pid = %d, ppid = %d\n", getpid(), getppid()); if((child1 = fork()) == 0)//子进程child1先抢到处理机资源并运行 {//子进程child1运行代码 for(int i = 1; i <= 10; i++) { printf("child1(进度 = %d%) is working!(pid = %d,ppid = %d)\n",i * 10, getpid(), getppid()); sleep(1); } printf("Child1 had completed!\n"); } else if(child1 > 0)//子进程没有抢到处理机资源,还需要判断子进程child2是否抢到 { if((child2 = fork()) == 0)//子进程child2抢到处理机资源并运行 {//子进程child2运行代码 for(int i = 1; i <= 10; i++) { printf("child2(进度 = %d%) is working!(pid = %d,ppid = %d)\n",i * 10, getpid(), getppid()); sleep(1); } printf("Child2 had completed!\n"); } else if(child2 > 0)//父进程parent抢到处理机资源并运行 { //父进程不阻塞,与子进程并发 waitpid(child1, NULL, WNOHANG); waitpid(child2, NULL, WNOHANG); for(int i = 1; i <= 3; i++)//父进程parent运行到30%时就提前退出 { printf("parent(进度 = %d%) is working\n", i * 10); sleep(1); } printf("Parent had Complete!\n"); } else if(child2 == -1) { printf("Error!\n"); } } else { printf("Error!\n"); } return 0; }
waitpid()不会阻塞父进程,父进程与子进程共同竞争资源,父进程完成后提前退出
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。