Linux基础之进程-fork()函数的详解

目录

一、前言

二、fork()函数

2.1 fork()函数的基本概念

2.2 问题一的解答

2.3 问题二的解答

2.4 问题三的解答

2.5 问题四的解答

2.6 问题五的解答


一、前言

       在上节内容中我们已经学会了使用我们的getpid()和我们的getppid()去查看我们进程的pid,并且学习到了两种查看进程的方式,在我们的正文开始之前,我先对上文的一些内容做一些补充。

       在第二种查看进程的方式中我们看到一个进程的详细信息:

即上图的右半部分,这里我们主要对其中的  cwd 和  exe 进行说明。
       我们经常会遇到一个概念,叫做文件的当前目录,那什么是当前目录呢,这是什么意思呢,子在进程中 cwd 就指向该进程的当前目录,其实就是在默认情况下,进程启动所在的路径,就是当前的工作目录。
       那 exe 又是什么呢,exe 指向的是可执行程序的位置。
       在Linux中我们可通过指令来修改当前的工作目录:

chdir  +  路径 :修改工作目录

二、fork()函数

2.1 fork()函数的基本概念+提出问题

       这里有一个问题,那就是如何去创建一个进程呢,最简单的方法就是执行我们的可执行程序,系统就会生成一个进程。我们还可以通过fork()这个函数在代码去主动去创建进程。

我们可以先用man指令查询一下这个函数:

       简单来说,fork()函数的作用就是创建一个当前进程的一个子进程。那我们要怎么理解去创建一个进程这样的一个概念呢?
       创建一个进程,其实就是系统申请内存,保存我们当前的可执行程序,生成其对应的一个PCB,并将该可执行程序及其PCB加入到我们的进程列表中。
       接下来就让我们先来看看fork()创建的进程有和特征。

      先写一段这样的代码,我们去观测一下该子进程的信息,至于为什么要这样写,我们等会再说,先跑起来看看。

我们会发现确实出现了两个进程,且其中一个进程的ppid是我们一个进程的pid。

       很明显,在我们的红色框框内第一个进程跟我们上节所讲的进程差不多,其父进程会是我们的命令行解释器。而这个第二个进程就应该是我们fork()函数所创建出来的子进程了。那我们再来看一段代码。

再来看看这段代码的运行结果。

       不难发现听音乐和下电影在同时运行,可是我们printf函数明明就只执行了一次为什么会输出两个不同的值,难道是我们的子进程继承了我们父进程的代码吗?就算是继承我父进程的代码,那我的fork()为什么会有两个返回值呢,这也太不符合我们之前所学了。那我们不妨把我们所有的问题全部抛出了一个一个解决。
        问题:

  1. fork()函数干了什么事,我们为什么要使用它?
  2. 为什么fork()函数会有两个不同的返回值?
  3. 为什么fork()的返回值会给父进程返回子进程的pid,而给子进程返回0?
  4. fork之后,子进程和父进程谁先执行?
  5. 如何去理解一个变量却又不同的返回值?

2.2 问题一的解答

       刚刚我们有讲,fork()函数的作用是创建了一个子进程,那这个子进程有什么用呢?
       我们创建子进程主要为了使用其有两个返回值的特性,来帮助我们实现多任务并行运行这一场景。举个例子,比如上文我们想边下载电影边听音乐的场景。可是我们新建出来的子进程按道理来说是不会有代码的,那其是如何满足我们的需求的呢?

       所以在fork之后,我们的父进程和我们的子进程会执行一样的代码,那这里可能就有人会问了,那fork之前的代码呢,子进程就不执行了吗? 是的,确实是不执行了,但是不是因为其看不到父进程的所有代码,而是子进程同样继承了父进程的寄存器。

2.3 问题二的解答

       问题又来了,为什么fork()会返回两个不同的值呢? 在上文我们有提到,一个进程是怎么被创建出来的,即当其可执行程序和PCB被加入到进程队列时,该进程就已经被创建成功了,那这个时候,fork()函数有没有结束呢? 没有,只能说其创建进程的任务完成了,但其还又一个语句没有执行呢,什么呢,那就是return。再回答第一个问题的时候我们就有提到,子进程会继承父进程的寄存器,那么此时寄存器是不是指向的是return语句呢? 很显然是的,那么父进程返回一个值,子进程返回一个值,不就有两个返回值了吗? 放张图,加深一下理解。

2.4 问题三的解答

为什么fork()的返回值会给父进程返回子进程的pid,而给子进程返回0呢?
这是因为父进程它很有可能不只有一个子进程,那其要是想对它的子进程进行管理该怎么做呢?那肯定是要根据其子进程的标识符呀,那么进程的标识符是什么呢,就是其pid。给自己的返回自己的pid没什么意义,所以fork就给子进程返回0。

2.5 问题四的解答

       创建完成子进程,这仅仅是一个开始,创建完成子进程之后,系统的其他进程,父进程,子进程都等着被系统调度执行。当父子进程的PCB都被创建且都在运行队列(操作系统会把其将要执行的代码放入一个队列中进行排队,这个队列就叫运行队列)中排队的时候,哪个进程先被调度,那个进程就先被执行。但是这个调度顺序是不确定的,由操作系统本身决定,由各自PCB中的调度信息(时间片、优先级等)+ 调度器算法共同决定的。

2.6 问题五的解答

为什么有两个返回值我们已经知道了,但是为什么这两个返回值不相同呢?
       这里就要提到,进程的独立性,其独立性首先就体现在各自的PCB是不会相互影响的。虽然父子进程共享代码,但是代码是只读的,无法被修改。但是数据却是可以被修改的,如果存在一个全局变量,我父进程需要根据这个全局变量作为判断条件,而我的子进程却会修改这个全局变量,那这不就影响到了我们的父进程了吗?所以数据每个进程都得想办法私有一份,怎么私有都拷贝下来吗,如果代码量很大的话,拷贝的代价就有点大了,而我们的操作系统是不会允许这样降低效率的事情发生的,那么我们该怎么办呢?
       这里主要是使用到了写时拷贝的方法,父子进程还是一样的共享代码,只有当自己要修改其中的某个变量时,才把这个变量拷贝过来,以达到不会相互影响的状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/620377.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dockerFile制作镜像、并远程发布

1、FORM 用于指定基础镜像,也就是在指定的镜像上,增加上后续dockerFIle中设置的内容(新的软件、新的服务等) FROM openjdk:8-jre 在这个容器中,就能直接使用java命令。 2、ENV 用于设置环境变量,在后续的R…

Android Compose 一:基础控件

Flutter 与 Compose 组件辣么像,难道是同一个google团队整的;也未深究,只是猜测。 创建项目 需要使用新版本Android studio,忽略步骤… 项目目录 MainActivity说明 1 系统默认页面 Preview 修饰的方法,只用来供开发…

物联网实战--平台篇之(七)应用界面设计

目录 一、米家APP分析 二、应用展示 三、应用列表 四、新建应用 五、重命名应用 本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.…

快速配置 Nginx 来实现 GPT 流式传输

目录 1. Nginx 参考配置2. Nginx 核心参数3. 其他参数 场景:代理 ChatGPT、代理各种 GPT 工具套壳等。 1. Nginx 参考配置 支持 GPT 流式访问的配置如下,请根据实际需求适当取舍即可: server {listen 80;server_name chat.test.com; # 绑…

PCIE协议-2-事务层规范-Message Request Rules-Vendor_Defined Messages

2.2.8.6 厂商定义消息 厂商定义消息允许扩展PCI Express消息功能,可以作为PCI Express规范的一般扩展,也可以是厂商特定的扩展。本节通用地定义了与这些消息相关的规则。 厂商定义消息(见表2-25)使用图2-28中显示的头标格式。re…

Nios实验使用串口输出“Hello Nios-II”字符到笔记本电脑

目录 实验过程 创建工程 修改程序 编译工程 运行项目 效果实现 总结 参考 实验过程 硬件设计见博主上篇博客 软件部分设计 下面使用 Nios II Software Build Tools for Eclipse 来完成当前项目的软件开发。 启动 Nios II SBT 按照下图所示点击 Nios II Software Build…

计算机网络复习-传输层

概念 传输层是进程与进程之间的通信使用端口(Port)来标记不同的网络进程端口(Port)使用16比特位表示(0~65535) UDP协议详解 UDP:用户数据报协议数据报:应用层传输过来的一个完整的数据不合并,不拆分 UDP的头部 UDP特点 UDP是无连接协…

【R语言篇】医学生福音,全球疾病负担数据库GBD 2021即将更新!!!

今天介绍即将于5月16日更新的全球疾病负担数据库GBD 2021,相信数据一经发表,过不了多久pubmed又将涌现一大波疾病负担相关文章。 Global Burden of Disease Study 2021 (GBD 2021) Data Resources | GHDx 在查找GBD相关文献方面,我个人还是比…

PS的文字点阵 文字边缘虚 为什么在Ps中打出来的字是带有锯齿状模糊的?

此方法主要针对低像素文字 关键部分 (4 封私信 / 80 条消息) 为什么在Ps中打出来的字是带有锯齿状模糊的? - 知乎 (zhihu.com)https://www.zhihu.com/question/54412515

【牛客】SQL211 获取当前薪水第二多的员工的emp_no以及其对应的薪水salary

1、描述 有一个薪水表salaries简况如下: 请你获取薪水第二多的员工的emp_no以及其对应的薪水salary, 若有多个员工的薪水为第二多的薪水,则将对应的员工的emp_no和salary全部输出,并按emp_no升序排序。 2、题目建表 drop table …

8个手机宝藏App,建议收藏!

AI故事视频生成,一站式生成小说漫画推文、儿童故事、民间故事等https://aitools.jurilu.com/ 1.地图车机版——百度地图 百度地图,作为新一代的人工智能地图,以其智能语音、智能导航系统、智能路线规划和智能推荐方案而著称。它不仅提供传统…

MATLAB模拟退火算法、遗传算法、蚁群算法、粒子群算法

概况 模拟退火算法、遗传算法、蚁群算法、粒子群算法等算法,都是属于概率算法,不绝对,不迅速,能用其它方式解决的问题,不要用这些相对复杂的算法,比如有明确的线性关系或者非线性对应关系。这里的概率算法…

IP跳变是什么,有什么作用?

IP跳变,简单来说,就是用户在使用网络时,不固定使用一个IP地址,而是定期或根据需求切换到另一个IP地址。这种技术为用户在网络环境中提供了一定的灵活性和安全性。 首先,我们来看看IP跳变的具体实现方式。当用户需要切…

CUDA-均值滤波算法

作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 实现原理 均值滤波是一种常见的图像处理方法,用于去除图像中的噪声。其原理很简单:对图像中的每个像素&a…

高频电源模块TL22010-T2整流模块TL22010-T3用途

直流屏充电模块TL22010-T2电源模块TL22010-T3,整流模块TL11010-T3,其他TL系列型号有:TL11020-T3,TL11010-T2,TL11020-T2,TL22010-T,TL-22010-T,TL-11010-T,TL-22005-T&am…

排序-选择排序(selection sort)

选择排序(selection sort)的工作原理非常简单:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾。选择排序的主要特点包括: 时间复杂度: 无论最好、最坏还是平均情况&…

【图像增强(空域)】基于灰度变换的图像增强及Matlab仿真

1. 摘要: 空域内的图像增强就是调整灰度图像的明暗对比度,对图像中各个像素的灰度值直接进行处理。常用的方法包括:灰度变换增强和直方图增强。 2. 原理: 灰度变换增强是空域ne对图像进行增强的一种简单且直接的方法。灰度变换…

26版SPSS操作教程(高级教程第二十章)

目录 前言 粉丝及官方意见说明 第二十章一些学习笔记 第二十章一些操作方法 神经网络与支持向量机 人工神经网络(artificial neural network,ANN) 假设数据 具体操作 结果解释 对案例的进一步分析 结果解释 ​编辑 尝试将模型复…

Pikachu 靶场 XXE 通关解析

前言 Pikachu靶场是一种常见的网络安全训练平台,用于模拟真实世界中的网络攻击和防御场景。它提供了一系列的实验室环境,供安全专业人士、学生和爱好者练习和测试他们的技能。 Pikachu靶场的目的是帮助用户了解和掌握网络攻击的原理和技术,…

软件测评中心详细介绍

软件产品已成为企业和个人工作中不可或缺的一部分。然而,面对市场上琳琅满目的软件产品,用户如何判断其质量、性能及是否满足自身需求呢?这时,软件测评中心的作用就显得尤为重要。本文将详细介绍软件测评中心的定义、功能及其重要…