fork函数为什么会有两个返回值
fork函数为什么会有两个返回值文章目录fork函数为什么会有两个返回值fork() 的基本行为为什么会有两个返回值核心原因**进程复制**执行流程分解为什么返回值不同设计目的**区分父进程和子进程**底层原理fork() 的实现1. 系统调用入口2. 核心函数 do_fork()3. 子进程从哪里开始执行写时复制Copy-on-Write优化完整示例验证两个返回值常见问题Q: fork() 后的代码会执行两次吗Q: fork() 返回两次那 fork() 函数本身执行了几次Q: 子进程如何知道自己是子进程Q: 为什么父进程返回子进程 PID而不是 1 或其他值总结总结这是关于 Linuxfork()系统调用的经典问题。fork()被称为调用一次返回两次的神奇函数。以下是详细解释fork()的基本行为#includeunistd.h#includestdio.hintmain(){pid_tpidfork();if(pid0){// 子进程执行这里printf(子进程: pid %d, 返回值为 %d\n,getpid(),pid);}elseif(pid0){// 父进程执行这里printf(父进程: pid %d, 返回值为 %d\n,getpid(),pid);}else{// fork 失败perror(fork error);}return0;}输出示例父进程: pid 1234, 返回值为 1235 子进程: pid 1235, 返回值为 0为什么会有两个返回值核心原因进程复制fork()执行时内核会创建一个新的进程控制块PCB复制父进程的task_struct复制父进程的内存空间写时复制技术优化为子进程设置新的 PID将子进程加入调度队列关键点fork()在父进程中执行一次但在返回前创建了子进程导致父进程和子进程各自从fork()返回。执行流程分解调用 fork() 前 父进程 P1 (pid100) 调用 fork() 内核创建子进程 P2 (pid101) P2 拥有 P1 的完整副本代码、数据、栈、堆 fork() 返回 父进程 P1 继续执行fork() 返回子进程的 PID (101) 子进程 P2 开始执行fork() 返回 0图示父进程执行 fork() ↓ 内核复制进程 ↓ 父进程 ← 返回 子进程PID ↓ ↓ (同时) ↓ 子进程 ← 返回 0为什么返回值不同设计目的区分父进程和子进程程序需要知道当前代码是在哪个进程中执行以便执行不同的逻辑返回值含义0当前是子进程0当前是父进程返回值是子进程的 PID-1fork 失败没有创建子进程pid_tpidfork();if(pid0){// 子进程执行的代码execlp(ls,ls,NULL);// 子进程执行其他程序}elseif(pid0){// 父进程执行的代码wait(NULL);// 等待子进程结束}底层原理fork()的实现1. 系统调用入口fork()实际上是调用内核函数sys_fork()不同架构略有不同// 简化版内核代码asmlinkagelongsys_fork(structpt_regs*regs){returndo_fork(SIGCHLD,regs-sp,regs,0,NULL,NULL);}2. 核心函数do_fork()// 极度简化的 do_fork 逻辑longdo_fork(...){structtask_struct*p;// 1. 复制 task_structpcopy_process(...);if(!IS_ERR(p)){// 2. 设置子进程的返回值p-pidget_new_pid();// 3. 将子进程加入就绪队列wake_up_new_task(p);// 4. 父进程返回子进程的 pidreturnp-pid;}return-1;}3. 子进程从哪里开始执行关键在于copy_process()中复制寄存器上下文staticstructtask_struct*copy_process(...){structtask_struct*p;// 复制父进程的 task_structpdup_task_struct(current);// 复制父进程的寄存器状态*p-thread.regs*current-thread.regs;// 关键修改设置子进程的返回值寄存器为 0p-thread.regs-ax0;// x86 架构中 eax/rax 存储返回值returnp;}在 x86 架构中系统调用返回值存放在eax32位或rax64位寄存器父进程的返回值是子进程 PID存放在寄存器中子进程复制了父进程的寄存器但内核特意将子进程的返回值寄存器改为 0写时复制Copy-on-Write优化现代 Linux 使用COW技术优化fork()fork()时并不真正复制父进程的物理内存父子进程共享相同的物理内存页但标记为只读当任一进程试图写入时触发缺页异常内核才复制该页好处fork()速度极快只需复制页表节省内存尤其是fork()后立即exec()的场景完整示例验证两个返回值#includestdio.h#includeunistd.h#includesys/wait.hintmain(){printf(开始: 只有一个进程 PID%d\n,getpid());pid_tpidfork();printf(fork 返回 %d, 当前进程 PID%d, 父进程 PID%d\n,pid,getpid(),getppid());if(pid0){// 父进程wait(NULL);printf(父进程结束\n);}elseif(pid0){// 子进程printf(子进程结束\n);}return0;}输出开始: 只有一个进程 PID1000 fork 返回 1001, 当前进程 PID1000, 父进程 PID999 (父进程) fork 返回 0, 当前进程 PID1001, 父进程 PID1000 (子进程) 子进程结束 父进程结束常见问题Q:fork()后的代码会执行两次吗A: 是的fork()之后的代码会在父子进程中各执行一次。fork();printf(这行会被打印两次\n);Q:fork()返回两次那fork()函数本身执行了几次A: 只执行了一次。是进程复制导致从同一个返回点有两个进程继续执行。Q: 子进程如何知道自己是子进程A: 通过检查fork()的返回值。内核特意设置子进程的返回值为 0。Q: 为什么父进程返回子进程 PID而不是 1 或其他值A: 父进程需要知道子进程的 PID 才能管理它如wait()、kill()。子进程可以通过getppid()获取父进程 PID。总结问题答案为什么有两个返回值fork()创建了子进程父子进程各自从fork()返回为什么返回值不同用于区分父子进程执行不同逻辑子进程返回值为什么是 0内核在复制进程后特意将子进程的返回值寄存器设为 0子进程从哪里开始执行从fork()返回处开始拥有父进程的完整副本内存如何复制使用写时复制COW技术优化一句话总结fork()通过复制当前进程创建子进程导致父子进程从同一返回点继续执行但内核通过设置不同的返回值让程序能区分当前是父还是子。总结这篇文章是作者搜集大量面经和资料这里出来的。感谢你的支持作者wkm是一名中国矿业大学(北京) 大一的新生希望得到你的关注如果可以的话记得一键三联

相关新闻

10分钟掌握FastHTML组件化开发:构建现代Web应用的核心技术

10分钟掌握FastHTML组件化开发:构建现代Web应用的核心技术

10分钟掌握FastHTML组件化开发:构建现代Web应用的核心技术 【免费下载链接】fasthtml The fastest way to create an HTML app 项目地址: https://gitcode.com/gh_mirrors/fa/fasthtml FastHTML是GitHub加速计划中的一个创新项目,它提供了创建HTM…

2026/7/3 6:24:40 阅读更多 →
深度解析BladeDISC:终极动态形状编译器完整指南

深度解析BladeDISC:终极动态形状编译器完整指南

深度解析BladeDISC:终极动态形状编译器完整指南 【免费下载链接】BladeDISC BladeDISC is an end-to-end DynamIc Shape Compiler project for machine learning workloads. 项目地址: https://gitcode.com/gh_mirrors/bl/BladeDISC BladeDISC是面向机器学习…

2026/5/17 12:22:32 阅读更多 →
Ink/Stitch:免费开源的机器刺绣设计终极指南

Ink/Stitch:免费开源的机器刺绣设计终极指南

Ink/Stitch:免费开源的机器刺绣设计终极指南 【免费下载链接】inkstitch Ink/Stitch: an Inkscape extension for machine embroidery design 项目地址: https://gitcode.com/gh_mirrors/in/inkstitch Ink/Stitch 是一款功能强大的免费开源 Inkscape 扩展&am…

2026/7/3 22:56:21 阅读更多 →

最新新闻

5分钟搭建本地Web漏洞靶场:PHPStudy+Xray实战指南

5分钟搭建本地Web漏洞靶场:PHPStudy+Xray实战指南

1. 项目概述与核心价值刚入行安全测试,你是不是也遇到过这样的尴尬:想动手练练Web漏洞挖掘,但找不到合适的靶场?网上的在线靶场要么太简单,要么访问不稳定,要么就是环境配置复杂到让人望而却步。我当年也是…

2026/7/3 23:22:16 阅读更多 →
3PEAK思瑞浦 TPCMP232-VS1R MSOP8 比较器

3PEAK思瑞浦 TPCMP232-VS1R MSOP8 比较器

特性 电源电压:2.7V至5.5V 低供电电流:每通道400mA 传播延迟:50纳秒 偏移电压:3.5mV 输入共模范围扩展至200mV 推挽输出

2026/7/3 23:20:16 阅读更多 →
本地部署AI绘画:Codex与Cowart打造离线无限画布工作站

本地部署AI绘画:Codex与Cowart打造离线无限画布工作站

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度 最近在尝试将AI绘画能力集成到本地工作流时,发现了一个痛点:很多在线AI绘画工具要么需要联网、要么功能受限…

2026/7/3 23:20:16 阅读更多 →
第 43 篇:连接超时完全指南:从抓包到根因,拆解每一段沉默

第 43 篇:连接超时完全指南:从抓包到根因,拆解每一段沉默

抓包实战系列第 23 篇 | 阅读时间:12 分钟 | 关键词:超时、抓包、TCP、排障 📌 为什么读这篇 线上报警里,“timeout” 出现频率排前三。 但大多数超时排查是这样展开的: 1. 应用报错:timeout 2. 看一眼日志:没头绪 3. 群里问:网络是不是有问题? 4. 网络组:我们正…

2026/7/3 23:16:14 阅读更多 →
基于DRV8213与STM32的智能散热系统设计与实现

基于DRV8213与STM32的智能散热系统设计与实现

1. 项目概述:基于DRV8213与STM32的智能散热系统设计在汽车电子和工业嵌入式系统中,散热管理直接关系到设备可靠性和寿命。最近完成的一个车载信息娱乐系统项目中,我们采用德州仪器的DRV8213电机驱动器控制MF25060V2-1000U-A99轴流风扇&#x…

2026/7/3 23:14:14 阅读更多 →
逆向分析短视频平台a_bogus参数:从JavaScript混淆到Python复现

逆向分析短视频平台a_bogus参数:从JavaScript混淆到Python复现

1. 项目概述:从“黑盒”到“白盒”的逆向之旅最近在分析某头部短视频平台的网页端接口时,一个名为a_bogus的参数频繁出现在我的视野里。无论是请求用户主页信息、抓取评论区数据,还是搜索商品列表,这个由一长串看似随机的字符组成…

2026/7/3 23:14:14 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻