当前位置: 首页 > news >正文

进程的创建——如何理解fork()系统调用

进程的创建

    • 前言
  • 前置知识补充(重要)
    • pid_t 的本质
    • 父进程和子进程
    • exit(0) & break & continue辨析
      • 1. 核心区别对比表
      • 2. 逐个拆解(附代码例子)
        • (1)`exit(0)`:结束“整个程序”
        • (2)`break`:跳出“当前循环/switch”
        • (3)`continue`:跳过“本轮循环剩余代码”
      • 总结
    • 代码初步解读
    • 代码进一步解读(如何理解调用fork返回两次)
    • 深入理解
    • 结语

前言

我们在操作系统中 总是说进程的创建 以及进程的切换等等 但是这个创建到底是怎么实现的呢 这个时候就需要借助fork()系统调用了所谓的系统调用无非是操作系统给我们用户提供的接口 使得我们能够请求操作系统的帮助去执行一些用户态下执行不了的特权指令等等
但是 在真正学习这个之前 我需要对于一些前置知识做出补充 这些都是我自己在学习的时候遇到的困惑 希望能帮到各位

  • 参考教材:【CSAPP-深入理解计算机系统】

前置知识补充(重要)

pid_t 的本质

  • 我先把我们本文需要重点理解的代码贴在下面 大家可以先看一下
  • 下面这段代码就是C 语言中利用 fork() 创建进程的经典示例,其核心是理解父子进程的内存空间独立这个关键点
  • 但是劳资看这个main函数怎么看怎么不对 到底哪不对呢 原来是pid这个变量类型我不清楚到底是什么东西
  • 于是就有了下文的解释:其实pid_t 不是 C 语言的内置类型(比如 int/long),而是操作系统(Linux/Unix)在头文件中定义的 “类型别名”,目的是统一表示 “进程 ID”。它的实际底层类型通常是 int 或 long
  • 简单说:pid_t 就是 “进程 ID 的专属类型”,本质是整数,只是系统给它起了个更专业的名字~
  • 一般来说这种经典教材上的这个变量名可不是乱取的 所以我们完全可以从英文全称的角度来理解 pid—— Process ID

父进程和子进程

  • 先建立直观认知:父进程 vs 子进程(生活比喻)
  • 你可以把进程理解为 “正在运行的程序”,就像一个正在工作的员工:
  • 父进程:相当于公司里的 “老员工”,它主动发起指令,创建出一个 “新员工”
  • 子进程:就是这个 “新员工”,它从老员工那里复制了一模一样的 “工作资料”(代码、变量、内存数据等),但拿到资料后,两人的工作是独立的 —— 新员工改自己的资料,不会影响老员工的,反之亦然。

exit(0) & break & continue辨析

你想弄清楚exit(0)continuebreak的区别,核心可以先记住:这三个都是用来“终止/跳过执行流程”的,但作用的范围、层级、效果完全不同——exit(0)是“结束整个程序”,break是“跳出当前循环/分支”,continue是“跳过本轮循环剩余代码”。

下面用通俗易懂的方式拆解,结合例子让你一眼分清:

1. 核心区别对比表

关键字/函数作用范围核心效果适用场景
exit(0)整个进程/程序直接终止当前运行的整个程序,返回状态码程序完成任务后退出、出错时终止
break当前循环(for/while)或 switch 分支跳出当前所在的循环/switch,执行后续代码满足条件时终止循环/分支
continue当前循环(for/while)跳过本轮循环剩余代码,直接进入下一轮循环满足条件时跳过本轮剩余逻辑

2. 逐个拆解(附代码例子)

(1)exit(0):结束“整个程序”
  • 本质:是一个系统调用函数(需要包含<stdlib.h>),不是关键字;

  • 效果:调用后,当前运行的进程(程序)立刻终止,所有代码都不再执行,0是返回给操作系统的“退出状态码”(表示正常退出);

  • 例子(对应你之前的进程代码):

    #include<stdio.h>#include<stdlib.h>intmain(){printf("程序开始\n");exit(0);// 程序直接终止printf("这段代码永远不会执行\n");// 不会打印return0;}

    运行结果只有程序开始,后面的代码完全不执行。

    补充:在你之前的父子进程代码中,子进程执行exit(0)只会终止子进程本身,父进程不受影响(因为父子进程是独立的)。

(2)break:跳出“当前循环/switch”
  • 本质:C语言关键字;
  • 效果:只能跳出当前所在的一层循环(for/while)或 switch 语句,程序会继续执行循环/switch 之外的代码;
  • 例子:
    #include<stdio.h>intmain(){for(inti=1;i<=5;i++){if(i==3){break;// 跳出整个for循环}printf("i = %d\n",i);}printf("循环结束,程序继续\n");// 会打印return0;}
    运行结果:
    i = 1 i = 2 循环结束,程序继续
(3)continue:跳过“本轮循环剩余代码”
  • 本质:C语言关键字;
  • 效果:不跳出循环,只是跳过当前轮次中continue之后的代码,直接进入下一轮循环的条件判断;
  • 例子:
    #include<stdio.h>intmain(){for(inti=1;i<=5;i++){if(i==3){continue;// 跳过本轮剩余代码,进入下一轮}printf("i = %d\n",i);}printf("循环结束\n");return0;}
    运行结果(缺少i=3):
    i = 1 i = 2 i = 4 i = 5 循环结束

总结

  1. exit(0):终止整个程序/进程,是“最高级”的终止;
  2. break:终止当前循环/switch,程序继续执行后续代码;
  3. continue:跳过本轮循环剩余代码,循环本身继续执行。

代码初步解读

  • 在知道上面这些之后我们再来看这段代码就大概能看出来在做一件什么事情了
  • 首先定义了两个变量pid x 并且将x的初始值置为1 然后用pid用于接收fork()函数的返回值
  • 接下来就是一个if语句 一旦pid=0 那么 就将x+1后 打印出来 child:x= _____; 终止进程
  • 如果没有进入就将x-1之后 再打印parent:x=_____ ;终止进程
  • 主要就是++x以及x++的区别
  • 这个时候我自己就非常疑惑 为什么会终止两次呢 这个时候就需要理解我们的fork()系统调用到底做了一件什么事情

代码进一步解读(如何理解调用fork返回两次)

  • 通常来说 调用一次函数只会返回一次 但是调用fork()确确实实的是会返回两次的
  • 一次是返回到父进程 一次是返回到新创建的子进程

  • 上面这张图片的右上角 就是我们执行输出的最终结果 这时候出现了一种奇怪的现象 为什么会打印出来两个结果呢 这本质上和上面为什么要终止两次进程是一个道理
  • 我们可以通过右下角的流程图得到答案
  • 对应在代码中:
  • 我们可以将main函数认为是父进程 在父进程中我们通过调用fork()创建出子进程 返回值为0
  • 执行 main() 函数的初始进程就是父进程,它的 x=1;
    调用 fork() 后,系统复制出一个子进程,子进程一开始也有 x=1(复制父进程的);
    子进程执行 ++x 把自己的 x 改成 2,父进程执行 --x 把自己的 x 改成 0,两者互不干扰。

深入理解

  • 总的来说 我们必须要明白的是 父进程和子进程是独立的进程 都有自己的私有地址空间 执行互不干扰
  • 并且这个时候我们就完全可以理解:为什么会有两个输出结果 其原因就是父进程调用fork()函数时 标准输出文件是打开的 而子进程继承了父进程所有打开的文件

结语

玛德 有种就放我进复试 球球 真没招了 本想抄个底 现在还真不知道到底是抄底还是抄顶 O(∩_∩)O哈哈~

http://www.cnnetsun.cn/news/484166.html

相关文章:

  • 学长亲荐!9款AI论文软件测评:研究生开题报告必备工具
  • 【VTK手册034】 vtkGeometryFilter 深度解析:高性能几何提取与转换专家
  • 抗干扰更强!8路PWM输出模块:隔离RS485/CAN通讯+占空比精准调节
  • vscode修改背景颜色为白色或者黑色-简单
  • 做开发找不到合适工作,程序员还有哪些新选择?
  • 程序员开发岗位求职难?这些优质出路值得一试
  • 别再死磕知识库了!2025 年大模型 TOP 5 场景出炉,第一名早就变天了!
  • Qoder NEXT 来了:补全功能全新升级,AI 代码采纳率提升 65%
  • django-python基于大数据技术的地铁短时客流预测系统的设计与实现_xk3513ir
  • springboot+vue的旅游数据分析可视化系统的设计与实现_149477ud
  • 安防摄像头电源接口阿赛姆TVS管防护方案
  • nginx接口超时,增加接口超时时间
  • 低耗能蓝牙信标:关键技术演变和部署深度选型指南详解
  • 通用、高效、且能处理复杂关联关系(多对多)的 “不同环境下实现数据“ 解决方案
  • Linux定时任务与自动化脚本实战
  • 深度测评继续教育AI论文网站TOP10:选对工具轻松写好论文
  • ROS-Industrial 安装及使用
  • 程序员必看!大模型“卖Token“模式即将崩盘?这才是真正的护城河与价值突围之路!
  • 课程论文还在 “东拼西凑”?虎贲等考 AI:3 小时产出 “高分范本”,逻辑深度双在线
  • 【Java毕设源码分享】基于springboot+vue的OA管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 算法题 最大频率栈
  • 知识管理工具又添新锐,notion vs sward一文对比解析
  • 当PLC遇上灌装线:手把手拆解产线控制逻辑
  • 无人驾驶车辆模型基于RLS算法预测控制侧偏刚度估算,递归最小二乘法在线识别前后轮胎侧偏刚度及大...
  • 学霸同款2026 AI论文写作软件TOP9:本科生毕业论文必备测评
  • 优雅的处理 API 接口敏感数据加解密(方案详解)
  • 《Light: Science Applications》超表面偏振态与偏振度完全独立控制新范式
  • Qwen3Guard-Gen-8B可用于简历生成内容真实性核查
  • Glitch项目内容审核:Qwen3Guard-Gen-8B保护开发者社区生态
  • Java程序员如何备战金三银四?