fork函数:
函数原型:pid_t fork(void);
返回值: 父进程返回子进程id,子进程返回0;失败返回-1(失败的原因:1内存不够;2系统进程数量太多);
注意:fork之前,父进程独立执行,fork之后,父子两个执行流分别执行。但是 父子进程谁先执行是由系统调度决定。
写实拷贝:父进程创建子进程后,子进程室父进程的副本;
返回值: 父进程返回子进程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保证子进程先运行,它调用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...