目录

一、fork函数初识

二、fork函数返回值

思考:

1. fork函数为何给子进程返回0,而给父进程返回子进程的PID?

2. 关于fork函数为何有两个返回值这个问题

三、写时复制机制

写时拷贝(Copy-On-Write)机制解析

1. 必要性:为什么需要写时拷贝?

2. 延迟拷贝的优势:为何不立即拷贝?

3. 代码段的写时拷贝适用性

关键结论

四、fork函数的常规用法

五、fork调用失败的原因:


一、fork函数初识

        在Linux系统中,fork函数是一个关键的系统调用,它通过复制现有进程来创建新进程。被创建的进程称为子进程,而原始进程则称为父进程。

#include <unistd.h>
pid_t fork(void);

函数返回值:

  • 子进程返回0
  • 父进程返回子进程的PID
  • 出错时返回-1

当进程调用fork函数时,内核会执行以下操作:

  1. 为子进程分配新的内存空间和内核数据结构
  2. 将父进程的部分数据结构内容复制到子进程
  3. 将子进程添加到系统进程列表
  4. fork函数返回,由调度器开始进行进程调度

        当进程调用fork()后,会生成两个二进制代码完全相同的子进程。这两个进程会从相同的执行点继续运行,但随后各自进入独立的执行流程。请看以下示例代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>int main(void) 
{pid_t pid;printf("Before: pid is %d\n", getpid());if ((pid = fork()) == -1) {perror("fork()");exit(1);}printf("After: pid is %d, fork return %d\n", getpid(), pid);sleep(1);return 0;
}

运行结果:

        输出内容分为三行:一行"Before"和两行"After"。进程2619首先打印"Before"消息,随后又打印了一条"After"消息。另一条"After"消息则是由进程2620打印的。值得注意的是,进程2620并未打印"Before"消息。为什么呢?如下图所示:

        在fork调用之前,父进程独立运行;调用之后,父进程和子进程将各自执行。需要注意的是,fork之后哪个进程先执行完毕,完全取决于系统调度器的安排。


二、fork函数返回值

  • 子进程返回0
  • 父进程返回子进程的PID
  • 出错时返回-1

思考:

1. fork函数为何给子进程返回0,而给父进程返回子进程的PID?

        这种设计源于进程间的关系特性:一个父进程可以创建多个子进程,但每个子进程只能有一个父进程。对子进程而言,它无需识别父进程;而对父进程来说,必须明确每个子进程的标识。父进程需要获取子进程的PID才能有效分配和管理任务。

2. 关于fork函数为何有两个返回值这个问题

当父进程调用fork函数时,系统会执行一系列创建子进程的操作:

  1. 创建子进程的进程控制块
  2. 建立子进程的进程地址空间
  3. 生成子进程对应的页表完成这些步骤后,操作系统会将子进程的进程控制块加入系统进程列表,此时子进程创建完成。

        换句话说,当fork函数执行return语句时,子进程的创建已经完成。因此,后续的return语句不仅由父进程执行,子进程也会执行同样的操作,这就解释了为何fork函数会返回两个值。


三、写时复制机制

        子进程刚创建时,与父进程共享相同的内存数据段和代码段,两者的页表都指向同一块物理内存区域。只有当父进程或子进程尝试修改数据时,系统才会执行写时复制操作,将原始数据复制一份供修改使用。

具体原理如下图所示:

        得益于写时拷贝技术,父子进程得以完全分离,从而确保了进程的独立性。写时拷贝是一种延迟申请技术,可以有效提高系统内存的使用效率。

这种在需要进行数据修改时再进行拷贝的技术,称为写时拷贝技术。

写时拷贝(Copy-On-Write)机制解析

1. 必要性:为什么需要写时拷贝?

  • 进程独立性要求
    多进程环境下,操作系统需确保各进程资源独占性。写时拷贝通过延迟拷贝策略,保证子进程修改数据时才会复制父进程资源,避免进程间数据干扰。

  • 性能优化
    直接拷贝父进程全部数据会带来显著开销(如内存占用、CPU复制时间),而多数情况下子进程可能仅读取数据或使用部分资源。

2. 延迟拷贝的优势:为何不立即拷贝?

  • 资源利用率

    • 避免冗余拷贝:子进程可能仅访问父进程部分数据(如只读代码段),立即全量拷贝会导致内存浪费。

    • 按需分配:仅在子进程尝试修改数据时触发拷贝,减少无效的内存占用(例如fork()后接exec()的场景无需拷贝父进程数据)。

  • 效率提升
    现代操作系统通过页表映射共享父进程资源,写时拷贝将实际拷贝操作推迟到最后一刻,显著降低进程创建开销。

3. 代码段的写时拷贝适用性

  • 常规情况(90%以上)
    代码段通常是只读的,父子进程可共享同一物理内存页,无需触发拷贝。

  • 例外场景

    • 进程替换(如exec():新程序加载会覆盖原代码段,此时需重新分配内存,本质上仍遵循"修改时拷贝"逻辑。

    • 自修改代码:极少见情况下程序动态修改代码段内容,会触发写时拷贝机制。

关键结论

写时拷贝通过共享只读、延迟写入的策略,在保证进程独立性的同时,最大化内存和计算资源的利用率,是操作系统优化进程创建的核心机制。


四、fork函数的常规用法

  • 父进程需要复制自身,使父子进程可以执行不同的代码段。例如,父进程监听客户端请求,创建子进程来处理具体请求。
  • 进程需要执行新程序。例如子进程在fork返回后调用exec函数。

五、fork调用失败的原因:

fork函数创建子进程也可能会失败,有以下两种情况:

  1. 系统中有太多的进程,内存空间不足,子进程创建失败。
  2. 实际用户的进程数超过了限制,子进程创建失败。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89220.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89220.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/89220.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软件开发】主流 AI 编码插件

主流 AI 编码插件1. GitHub Copilot 支持平台&#xff1a;VS Code、Neovim、JetBrains 系列、Visual Studio 优点 深度语料库&#xff1a;基于 OpenAI 的大规模模型训练&#xff0c;能够生成高质量、上下文相关的代码补全。多语言支持&#xff1a;对 Python、JavaScript、TypeS…

实训十一——网络通信原理

补充如何解决IPv4地址不足的问题&#xff1f;使用专用的IPv4地址范围&#xff08;如 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16&#xff09;并通过NAT转换与外部网络通信&#xff0c;能有效节约公网IPv4地址。根据RFC 1918的定义&#xff0c;以下是保留的私有IPv4地址范围&am…

Spring Cloud LoadBalancer 详解

在分布式系统快速发展的当下&#xff0c;服务间的调用日益频繁且复杂。如何合理分配请求流量&#xff0c;避免单个服务节点过载&#xff0c;保障系统的稳定性与高效性&#xff0c;成为关键问题。负载均衡技术便是解决这一问题的重要手段。Spring Cloud LoadBalancer 作为 Sprin…

Linux内核内存管理相关的配置参数

Linux内核内存管理相关的配置参数&#xff08;主要位于/proc/sys/vm/目录下&#xff09;&#xff0c;用于调整内存分配、缓存管理、交换机制、OOM&#xff08;内存溢出&#xff09;策略等核心内存行为。以下是对每个参数的详细解释&#xff1a; admin_reserve_kbytes block_dum…

Web开发 01

先放一下自己写的手敲的第一个网站代码&#xff01;~虽然很简单但还是有点成就感&#xff01;&#xff01;开心&#x1f60a;<!DOCTYPE html> <html><head><title>Title!</title><link rel "stylesheet"href "style.css"…

Redis 生产实战 7×24:容量规划、性能调优、故障演练与成本治理 40 条军规

&#xff08;一&#xff09;写在前面&#xff1a;为什么需要“军规” Redis 在测试环境跑得飞快&#xff0c;一到线上就“莫名其妙”抖动&#xff1b;大促前扩容 3 倍&#xff0c;成本却翻 5 倍&#xff1b;一次主从切换&#xff0c;缓存雪崩导致下游 DB 被打挂&#xff1b;开发…

【DOCKER】综合项目 MonitorHub (监控中心)

文章目录1、项目架构图1.1 架构组件2、实际实施2.1 安装docker2.2 编写dockerfile文件2.2.1 Prometheus2.2.2 node_exporter2.2.3 nginxvts模块2.2.4 nginx_exporeter 服务发现文件2.2.5 maridb dockerfile文件2.2.6 镜像总数2.3 具体操作2.3.1 Prometheus组件2.3.2 nginx组件2…

Java List 集合详解:从基础到实战,掌握 Java 列表操作全貌

作为一名 Java 开发工程师&#xff0c;你一定在项目中频繁使用过 List 集合。它是 Java 集合框架中最常用、最灵活的数据结构之一。无论是从数据库查询出的数据&#xff0c;还是前端传递的参数列表&#xff0c;List 都是处理这些数据的首选结构。本文将带你全面掌握&#xff1a…

SGMD辛几何模态分解 直接替换Excel运行包含频谱图相关系数图 Matlab语言!

SGMD辛几何模态分解 直接替换Excel运行包含频谱图相关系数图 Matlab语言算法近几年刚提出&#xff0c;知网还没几个人用&#xff0c;你先用&#xff0c;你就是创新&#xff01;算法新颖小众&#xff0c;用的人很少&#xff0c;包含分解图、频谱图、相关系数图&#xff0c;效果如…

Oracle数据泵详解——让数据迁移像“点外卖”一样简单​

​今天我想和大家聊一个数据库领域的“万能搬运工”——Oracle数据泵&#xff08;Data Pump&#xff09;​。相信很多人都有过这样的经历&#xff1a;业务要上线新系统&#xff0c;得把旧库的数据搬到新环境&#xff1b;或者领导突然要一份3年前的历史数据&#xff0c;可不能影…

Leetcode 03 java

爬楼梯算法现在只看明白动态规划&#xff0c;也没有很难哟&#xff01;&#xff01;题目70. 爬楼梯假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f;java题解class Solution {public int climbStairs(…

怎么删除 wps 的右键菜单

打开 WPS 点击 WPS Office 选项卡&#xff0c;点击右侧全局配置》配置和修复工具点击高级功能定制下的都可以关闭和隐藏点击确定就可以了。

C++:list

一&#xff0c;list的介绍1&#xff0c;list初步&#xff08;1&#xff09;list是 C 标准模板库 (STL) 中的一个双向链表容器。它允许在常数时间内进行任意位置的插入和删除操作&#xff0c;但不支持随机访问。&#xff08;2&#xff09;list容器的底层数据结构为带头双向循环链…

深入理解Collections.addAll方法

文章目录深入理解Collections.addAll方法概述方法定义基本用法1. 向List添加元素2. 向Set添加元素3. 添加数组元素与传统add方法的比较使用传统add方法使用Collections.addAll性能考虑注意事项实际应用场景与Collection.addAll的区别最佳实践总结深入理解Collections.addAll方法…

CISP-PTE 练习题(完整一套)

目录 1、SQL注入 2、文件上传 3、文件包含 4、代码审计 5、命令执行 6、端口扫描 7、sql 写 webshell 8、3389 远程桌面利用 1、SQL注入 sqllabs-less-24 二次注入 2、文件上传 没有对文件后缀进行检测&#xff0c;但是对文件类型有检测&#xff0c;需要使用图片头绕…

Vue3入门-计算属性+监听器

&#x1f3e0;个人主页&#xff1a;Yui_ &#x1f351;操作环境&#xff1a;vscode\node.js &#x1f680;所属专栏&#xff1a;Vue3 文章目录1. 计算属性1.1 computed函数1.2 计算属性VS普通函数1.3 计算属性的完整写法2. 监听器3.总结1. 计算属性 计算属性&#xff08;compu…

Linux Swap区深度解析:为何禁用?何时需要?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、Swap区&#xff1a;Linux的"内存救生圈"二、为什么要禁用Swap&#xff1f;性能的隐形杀手三、何时应该使用Swap&#xff1f;不可或缺的场景四、如…

用TensorFlow进行逻辑回归(三)

逻辑回归Logistic regression这个脚本展示如何用TensorFlow求解逻辑回归。 ()ysigmoid(Axb)我们使用低出生重量数据,特别地:y 0 or 1 low birth weightx demographic and medical history dataimport matplotlib.pyplot as pltimport numpy as npimport tensorflow as tfimp…

mingw 编译 assimp v6.0.2 解决编译报错

mingw 编译 assimp v6.0.2 理论上看这个就能满足&#xff1a;在Windows下使用CMakeMinGW64编译Assimp库 环境变量问题 i386 architecture of input file CMakeFiles\assimp.dir/objects.a(assimp.rc.obj)’ is incompatible with i386:x86-64 output collect2.exe: error: ld r…

Windows 11清理C盘方法大全:磁盘清理/禁用休眠/系统还原点/优化大师使用教程

Windows 11清理C盘方法1. 使用磁盘清理工具步骤&#xff1a;按 Win S 搜索“磁盘清理”&#xff0c;打开工具。选择C盘&#xff0c;点击“确定”。勾选需要清理的文件类型&#xff08;如临时文件、系统错误内存转储等&#xff09;&#xff0c;点击“确定”。确认删除操作&…