fork函数和vfork函数

fork函数:
函数原型:pid_t fork(void);
返回值: 父进程返回子进程id,子进程返回0;失败返回-1(失败的原因:1内存不够;2系统进程数量太多);
注意:fork之前,父进程独立执行,fork之后,父子两个执行流分别执行。但是 父子进程谁先执行是由系统调度决定。
写实拷贝:父进程创建子进程后,子进程室父进程的副本;
父子代码共享,父子不写入时,数据也是共享。当任意一方试图写入时,便以 写实拷贝的方式各自创建一份副本
代码块:
 
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<fcntl.h>
  5 #include<sys/stat.h>
  6 #include<stdlib.h>
  7 int main()
  8 {
  9     int val=100;
 10     pid_t pid=fork();
 11     if(pid==0){
 12         val=42;
 13         printf("val=%d\n",val);
 14         printf("child:pid=%d    ppid=%d\n",getpid(),getppid());
 15         exit(0);
 16     }else{
 17         sleep(5);//父进程先睡觉,再输出,睡觉这个过程子进程把val值改了
 18         printf("val=%d\n",val);
 19         printf("child:pid=%d    ppid=%d\n",getpid(),getppid());
 20         exit(1);
 21     }
 22 }

运行结果:

vfork()函数:
vfork创建的子进程与父进程共享地址空间,即子进程完全运行在父进程的地址空间上,子进程对虚拟地址空间的修改同样为父进程所见,用vfork创建子进程后,父进程会被阻塞到子进程调用exec或exit之后才运行。
vfork保证子进程先运行,它调用exec或exit后父进程才能调度运行,fork的父子进程运行顺序不定,谁先运行取决于内核的调度算法。父进程中的数据空间和堆、栈可能会产生副本,具体情况要看使用的是fork还是vfork,fork产生副本,vfork则共享这部分内存。
vfork避免了(fork函数子进程被创建后,仅仅为调用exec执行另一个程序,它对地址空间的复制是多余的)这个问题,减少了不必要的开销
代码块:
  
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<fcntl.h>
  5 #include<sys/stat.h>
  6 #include<stdlib.h>
  7 int main()
  8 {
  9     int val=100;
 10     pid_t pid=vfork();//子进程与父进程共享地址空间
 11     if(pid==0)
 12     {
 13         val=42;
 14         printf("val=%d\n",val);
 15         printf("child:pid=%d    ppid=%d\n",getpid(),getppid());
 16         sleep(5);就算是子进程睡了5秒,父进程也不会先执行
 17         exit(0);
 18     }else{
 19         printf("val=%d\n",val);//注意val的值已经被改变
 20         printf("father:pid=%d    ppid=%d\n",getpid(),getppid());
 21         exit(1);
 22     }
 23     return 0;
 24 }

运行结果:
OVER...

猜你喜欢

转载自blog.csdn.net/komacc/article/details/80290397
今日推荐