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!!!记住!
相关推荐
张书名2 小时前
《强化学习数学原理》学习笔记7——从贝尔曼最优方程得到最优策略
笔记·学习
我命由我123452 小时前
Photoshop - Photoshop 工具栏(1)移动工具
笔记·学习·ui·职场和发展·求职招聘·职场发展·photoshop
努力学习的小廉2 小时前
深入了解linux网络—— 基于UDP实现翻译和聊天功能
linux·网络·udp
大聪明-PLUS3 小时前
从技术史看:Unix 从何而来
linux·嵌入式·arm·smarc
励志不掉头发的内向程序员3 小时前
【Linux系列】并发世界的基石:透彻理解 Linux 进程 — 进程概念
linux·运维·服务器·开发语言·学习
A9better3 小时前
嵌入式开发学习日志30——stm32之定时器中断简单项目练习
stm32·单片机·嵌入式硬件·学习
---学无止境---4 小时前
Linux中内核堆栈跟踪函数dump_stack的实现
linux
早起的年轻人4 小时前
CentOS 8系统盘大文件查找方法
linux·运维·centos
心灵宝贝4 小时前
Linux CentOS 7 安装 zip-3.0-11.el7.x86_64.rpm 详细步骤(命令行教程)(附安装包)
linux·运维·centos