fork函数

  复制进程映像:使用fork函数得到的子进程从父进程继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程
优先级、进程组号当前工作目录、根目录、资源限制、控制终端等。
  

  子进程与父进程的区别在于:
1、父进程设置的锁,子进程不继承(例如对于一个排他锁,父进程设置了锁,子进程再设置,显然不合适)
2、各自进程ID和父进程ID不同
3、子进程的未决警告被清除
4、子进程的未决信号集设置为空集
 #include <unistd.h>

#include <sys/types.h>

 pid_t   fork(void);//无参数,失败返回-1。两次返回是在各自的地址空间中返回的
A 进程fork进入内核 

孤儿进程:父进程先于子进程退出,托孤给init进程
僵尸进程:子进程先退出,父进程还未查询子进程的退出状态,子进程就处于僵死状态(defunct)。

为何父进程返回值大于0(新进程ID号码),子进程返回0:因为子进程PCB中保存有进程ID和父进程ID,所有即便返回0,子进程也能获取这两个值;但父进程若返回0,则它

无法得知新创建的子进程的ID。

fork一次调用两次返回(是在各自的进程地址空间中返回的),fork成功,意味着创建了一个进程副本,两个进程。fork陷入内核,拷贝父进程代码,所以子进程也有fork,并返回。

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<stdlib.h>
 4 #include<stdio.h>
 5 #include<errno.h>
 6 #include<string.h>
 7 #include<signal.h>
 8 #define ERR_EXIT(m)
 9     do
10     {
11         perror(m);
12         exit(EXIT_FAILURE);
13     }while(0)  //宏要求一条语句
14 
15 int main()
16 {
17     signal(SIGCHLD,SIG_IGN);//避免僵死进程
18     printf("before fork pid=%d
",getpid());
19     pid_t pid;
20     pid=fork();//进程代码段、数据段、堆栈段等一样,新进程的堆栈段和PCB也跟父进程一样,所以下一条指令地址也一样,所以不会从开头运行。所以进程分支在fork之后。
21     if(pid==-1)
22         ERR_EXIT("fork error");
23     if(pid>0)
24     {
25         printf("this is parent pid=%d, child pid=%d
",getpid(),pid);
26     }
27         
28     else if(pid==0)
29     {
30         //sleep(5);//父进程先结束
31         printf("this is child pid=%d, parent pid=%d
",getpid(),getppid());
32     }
33         
34     return 0;
35 }
36 /*
37 子进程先结束
38 before fork pid=48714
39 this is parent pid=48714, child pid=48715
40 this is child pid=48715, parent pid=48714
41 */

   fork函数陷阱:1-->2-->4-->8  (核心:fork开始,会有两个进程执行相同代码段)

#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#define ERR_EXIT(m)
    do
    {
        perror(m);
        exit(EXIT_FAILURE);
    }while(0)  //宏要求一条语句
int main()
{
    fork();
    fork();
    fork();
    printf("ok
");
    return 0;
/*8
ok
ok
ok
ok
ok
ok
ok
ok
*/
}

  写时复制(copy   on  write):

如果多个进程要读取(仅仅读取)它们自己的那部分资源的副本,那么复制是不必要的(比如代码段),每个进程只要保存一个指向这个资源的指针就可以了。如果一个进程要修改自己那份资源的副本,那么就会复制那份资源。这就是写时复制。资源需要修改才要复制。其他进程仍然共享。实际上不会被修改的数据是共享的。

原文地址:https://www.cnblogs.com/wsw-seu/p/8299002.html