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...