赞
踩
先来认识认识fork
fork()函数是创建进程函数。 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
其函数原型为:
pid_t fork( void);
当调用fork()时,将执行以下动作:
向系统申请一个新PID
创建子进程,复制父进程的PCB,获得父进程的数据空间、堆、栈等资源的副本
在父进程中返回子进程的PID,在子进程中返回0
执行完以上动作后,父进程和子进程便开始并发执行了。
需要注意的是:
这也就是说, 在fork函数执行完毕后 ,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。
vfork函数在后面
接下来我们通过几个demo来实现看看
demo1:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid;
pid =getpid();
fork();
printf("pid is %d\n",pid);
return 0;
}
打印结果如下:
pid is 7964
pid is 7964
我们可以看到,通过执行fork函数,我们得到了两次打印,这个demo分不清楚父进程和子进程,接着看看demo2
demo2:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(){ pid_t pid; pid_t rpid; pid =getpid(); printf("before fork pid :%d\n",pid); rpid = fork(); printf("after fork pid :%d\n ",rpid); printf("pid is %d\n",getpid()); return 0; }
定义一个retpid,接收fork的返回值,在fork之前我们看到pid是8188,fork之后pid是8189,也就是在这里创建了一个子进程。通过下面的printf得知,父进程是8188,它返回子进程的pid;fork返回两个值,一个是子进程的id,另一个是0,所以第二次打印after fork pid :0,显示当前子进程的pid是8189。
before fork pid :8188
after fork pid :8189
pid is 8188
after fork pid :0
pid is 8189
接下来看看demo3
demo3
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(){ pid_t pid; pid_t rpid; pid =getpid(); printf("before fork pid :%d\n",pid); rpid = fork(); // printf("after fork pid :%d\n ",rpid); if(pid == getpid()){ printf("father pid is %d\n",getpid()); }else{ printf("child pid is %d\n",getpid()); } return 0; }
fork 创建进程后,先执行第一个,如果我的pid和当前getpid一致,就表明此时是父进程在执行操作;如果不一致,也就是子进程在执行,此时的getpid等于rpid
before fork pid :8356
father pid is 8356
child pid is 8357
demo4
通过返回值来判断
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int main(){ pid_t pid; pid_t rpid; int count = 0; pid =getpid(); printf("before fork pid :%d\n",pid); rpid = fork(); if(rpid > 0){ printf("father pid is %d\n",getpid()); count++; }else if(rpid == 0){ printf("child pid is %d\n",getpid()); count++; }else{ printf("error!\n"); exit(-1); } return 0; }
这样很清楚,fork的返回值是childpid和0
before fork pid :8643
father pid is 8643
child pid is 8644
vfork也可以创建进程,与fork有什么区别呢?
区别一:vfork可以直接使用父进程存储空间,不拷贝
区别二:vfork可以保证子进程先运行,当子进程调用exit退出后,父进程才执行
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t vfork(void);
下面看看这个demo
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int main(){ pid_t pid; int count = 0; pid =getpid(); pid = vfork(); if(pid > 0){ while(1){ printf("father pid is %d\n",getpid()); sleep(1); } }else{ while(1){ printf("child pid is %d\n",getpid()); sleep(1); count++; if(count == 3){ exit(0); } } } return 0; }
使用vfork函数首先保证子进程执行完,在执行父进程,在代码中,子进程执行三次,父进程才执行。
看看结果:
而如果把其中的while循环代码换一下,使用fork函数执行,就会发现子进程和父进程交替执行,或者是依据系统调度交替执行
pid = fork();
if(pid > 0){
while(1){
printf("father pid is %d\n",getpid());
sleep(1);
}
}else{
while(1){
printf("child pid is %d\n",getpid());
sleep(1);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。