linux学习笔记(11)fork详解

复制进程: fork(在unistd.h)

fork****系统调用会创建一个新的进程,称为子进程
而调用fork的进程被称为父进程
子进程是父进程的一个副本,它会复制父进程的地址空间(包括代码段、数据段、堆、栈等)、打开的文件描述符、进程的状态等大部分资源。

返回值

fork 调用会在父进程和子进程中都返回,但是返回值不同:
在父进程中,fork 返回子进程的进程 ID**(是一个大于 0 的整数)** 。这可以让父进程知道自己创建的子进程的标识,以便后续进行管理,比如使用 wait 系列函数等待子进程结束。
在子进程中,fork 返回 0。通过返回值 0,子进程可以知道自己是新创建的子进程,从而执行与父进程不同的代码逻辑。
如果 fork 调用失败,它会在父进程中返回 -1,并设置适当的错误码(比如内存不足等情况导致无法创建新进程)。

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
int main(){
    int n = 0;
    char* s = NULL;
    pid_t id = fork();
    if( id == -1 )exit(1);
    if( id == 0 ){
        n = 3;
        s = "child";
    }
    else{
        n = 7;
        s = "parent";
    }    
    for(int i = 0; i < n; i++ ){
        printf("s=%s ,pid=%d\n",s,getpid());
        sleep(1);
    }
    return 0;
}

注意事项

虽然子进程复制了父进程的大部分资源,但并不是完全共享所有内容。
比如,父子进程有各自独立的地址空间,对同一个变量的修改在不同进程中不会相互影响。
不过,像打开的文件描述符这类资源,在父子进程中是共享引用的(但操作是独立的)。
fork 调用后,父子进程执行的先后顺序是不确定的,这取决于操作系统的调度算法。

fork****的核心工作原理和特性

写时复制(Copy-on-Write, COW)

这是理解 fork 效率的关键。早期的 fork 会立即复制父进程的全部内存空间,如果父进程很大,这会非常耗时耗资源。
现代的 fork 采用了写时复制技术。创建子进程时,内核并不会立即复制物理内存页 ,而是让父进程和子进程共享所有的内存页,并将这些页标记为"只读"。
当父进程或子进程任何一方 尝试修改某一块内存时,内核才会在修改前复制这一块内存页 ,然后让修改方在自己的副本上进行操作。这样就大大提高了 fork 的效率,因为很多进程在 fork 后会立即执行 exec(见下文),根本不会修改大部分内存。
返回值:区分父子进程的关键
fork() 函数最神奇的地方是它被调用一次,但返回两次
父进程 中,fork() 返回新创建子进程的进程ID(PID)(一个大于0的数字)。
子进程 中,fork() 返回 0
如果创建失败(例如系统资源不足),则返回 -1
通过判断返回值,程序就可以让父进程和子进程执行不同的代码路径。
fork() 成功返回时,子进程已经被创建了。 它拥有独立的PID、内核数据结构和一个完整的、逻辑上独立的地址空间视图。但是,这个地址空间所对应的物理内存资源,在初始阶段是与父进程共享的,并通过"写时复制"机制在需要修改时才进行真正的分配和复制。

cow的执行界限:

会触发COW的操作:

  1. 赋值操作 :var = new_value
  2. 自增/自减 :var++, ++var, var--
  3. 复合赋值 :+=, -=, *=, /=
  4. 通过指针修改 :*ptr = value
  5. 数组成员修改 :array[index] = value
  1. 结构体成员修改 :struct.member = value
    不会触发COW的操作:
  1. 读取操作 :printf("%d", var)
  2. 取地址 :&var
  3. 条件判断 :if (var > 0)
  4. 表达式计算 :result = var + 10
  5. 函数参数传递 :func(var)(传值)
  1. 返回值的读取 :return var;
    修改结构体其中某个变量,会复制一整个结构体
    修改较大的数组其中一个元素,复制整个内存页(通常是4kb)
    修改哪里就cow哪里!!!剩下没修改的就不cow!!!记住!
相关推荐
盐焗西兰花3 小时前
鸿蒙学习实战之路:状态管理最佳实践
学习·华为·harmonyos
小糖学代码4 小时前
LLM系列:1.python入门:3.布尔型对象
linux·开发语言·python
shizhan_cloud4 小时前
Shell 函数的知识与实践
linux·运维
Deng8723473484 小时前
代码语法检查工具
linux·服务器·windows
小毅&Nora5 小时前
【人工智能】【深度学习】 ⑦ 从零开始AI学习路径:从Python到大模型的实战指南
人工智能·深度学习·学习
Maxwell_li15 小时前
Pandas 描述分析和分组分析学习文档
学习·数据分析·numpy·pandas·matplotlib
雷工笔记5 小时前
MES学习笔记之SCADA采集的数据如何与MES中的任务关联起来?
笔记·学习
繁星星繁6 小时前
【C++】脚手架学习笔记 gflags与 gtest
c++·笔记·学习
霍夫曼6 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
2301_810746316 小时前
CKA冲刺40天笔记 - day20-day21 SSL/TLS详解
运维·笔记·网络协议·kubernetes·ssl