fork函数的那些事儿

    xiaoxiao2023-11-29  158

    提到fork()函数就不得不提到父子进程,子进程是以父进程为模板通过fork()函数来创建的.父子进程共享,各自开辟空间(子进程会把父进程的虚拟地址空间拷贝一份,作为子进程的地址空间),拥有自己的进程.

    一:父进程与子进程之间的约定

    父进程返回子进程的pid

    fork()函数成功子进程返回0

    fork()函数执行失败,返回值为-1

    1:失败的原因有两种:

    1.内存不够,导致子进程无法继续申请地址空间

    2.进程太多,导致申请失败

    【注】:父子进程执行顺序没有先后关系,全靠调度器实现

    2: 验证父子进程返回值
    #include<stdio.h> #include<unistd.h> int main(){ //__pid_t和pid_t还有int 都是等价的 pid_t ret=fork(); if(ret>0){ //father printf("father:%d\n ",getpid()); } else if(ret== 0){ //child printf("child:%d\n",getpid()); }else{ perror("fork"); } sleep(1); return 0; }
    3:【小结】:
    父进程返回子进程的pid,子进程返回0通常需要让父子进程执行不同的逻辑,就可以借助fork的返回值来进行区分

    二:神奇的fork()与缓冲区的秘密

    #include<stdio.h> #include<unised.h> int main(){ for(int i=0;i<2;++i){ fork(); printf("="); //第一次执行完后没有刷新缓冲区,所以第二次执行子进程缓冲区中还有了第一次的 = } return 0; }

    代码的运行结果你猜的出来吗? 其实这里面还是有点东西的.

    程序的运行结果截图

    可以看到运行结果中有8个 = ,这是为啥呢?

    原理图示

    原函数(父进程)在第一次运行的过程中通过 fork() 函数创建了自己的子进程,所以第一次循环结束的时候父子进程各自在缓存区产生了一个 "="。

    原函数执行第二次循环的时候其第一次运行结果还在缓冲区,所以在第二次产生子进程的时候会将第一次的结果也拷贝到第二次产生的子程序中(第二次循环产生的子程序天生就带有一个 = 号)所以第二次产生的子进程结束时带有两个 = 号 而对应父进程(第一次循环的父进程和子进程)又产生一个**=,则第二轮循环产生了六个=**,加上之前产生的两个 = 一共有 8个等号

    例二
    #include<stdio.h> #include<unised.h> int main(){ for(int i=0;i<2;++i){ //执行了两次 fork(); //会创建子进程 printf("="); fflush(stdout);//第一次刷新完缓冲区后,缓冲区的内容就为空了 } return 0; }

    运行结果

    可以看到屏幕上打印了6个等于号

    原因很简单奥,是因为循环第一次执行完后。刷新缓冲区将第一次执行的结果打印到了频幕上,所以缓冲区为空了,第二次循环是产生的子进程是为空的没有继承第一次循环的结果。

    原理图示

    【小结】:
    在循环过程中子进程是否会继承父进程上一次的运行结果取决于上一次循环结束时缓冲区是否为空。
    最新回复(0)