Linux进程——子进程的创建(fork的原理)

news/2024/5/17 10:12:47

前言:在上一篇文章中,我们已经会使用getpid/getppid函数来查看pid和ppid,本篇文章会介绍第二种查看进程的方法,以及如何创建子进程!


在这里插入图片描述


本篇主要内容:

  • 查看进程的第二种方法
  • 创建子进程
  • 系统调用函数fork

在这里插入图片描述


在开始前,我先来回顾一下如何获取pid,ppid
在这里插入图片描述

进程要想区分就一定会有唯一的标示符,而pid,ppid初始化后就变为内核中的数据,也就是操作系统里的数据,在我们自己开发时,操作系统不会将内部数据暴露出来,不能直接访问,所以通过系统调用接口直接获取pid,ppid。

目录

  • 1. 查看进程的第二种方法
  • 2. 创建子进程
    • 2.1 系统调用函数fork
    • 2.2 fork的一般写法
    • 2.3 fork的原理
  • 3. 总结


1. 查看进程的第二种方法

在Linux系统中,不只有ps能够查看进程,还存在着一个动态目录proc,该目录存放了所有存在的进程,目录的名称。它会随着进程的改变而随时更新它的内容!

查看所有进程:
指令:ls /proc/

在这里插入图片描述

查看指定pid的进程文件:
指令:ls /proc/进程pid

如果想只查看这个目录我们可以:
指令:ls /proc/进程pid -dl

proc查看进程

当我们结束这个进程时,文件也会从proc中被删除


误删可执行程序时

在看完这个视频后,我们发现当我们在程序运行时,误删了可执行程序,进程不会被终止,但是在proc目录中的exe被标红并注明delete

在自行创建的进程中,我们只需要掌握好两个文件cwdexe

  • cwd代表当前工作目录
  • exe指向可执行程序的位置

默认情况下,进程启动所处的路径,就是当前路径,pwd指令其实就是从cwd中找到当前路径的!

当前工作目录是可以通过系统调用进行修改的:
指令:chdir ( " 路径 " )

我们只需要在代码编写时,加入这条指令我们就能更改当前工作目录


2. 创建子进程

2.1 系统调用函数fork

在Linux中,进程的创建方式有两种:

  • 命令行中直接启动进程
  • 通过代码创建

而在用代码创建进程时,实则是进行了系统调用,这里我们就得在学习一个系统调用函数fork!

函数:fork

让我们来简单用man指令了解fork函数信息
在这里插入图片描述
fork的功能是创建一个子进程
让我们来简单实现以下fork
在这里插入图片描述

在这里插入图片描述
我们发现在fork之后函数printf调用了两次!!!

我们再来看看进程的ppid
在这里插入图片描述
在这里插入图片描述

  • 说明了一个情况:fork之后,会创建子进程,并且子进程会和父进程一起进入后面的函数并且分别执行一次

2.2 fork的一般写法

结合目前: 只有父进程执行fork之前的代码(一定),fork之后,父子进程都要执行后续的代码!

  • 因此我们推断fork函数不仅会帮我们创建子进程而且它还有两个返回值,fork成功的时候,会有两个不同的返回值,给子进程返回0,给父进程返回子进程的pid。

首先我们来思考以下问题:

那么我们为什么要创建子进程?子进程的作用是啥?

  • 我们想让子进程协作父进程完成一些工作,这些工作是单进程解决不了的,因此子进程的创建是为了协助父进程,因此父子进程做的是不一样的事情

我们怎么保证父子进程做的是不一样的事情呢?

  • 我们可以通过判断fork的返回值,判断谁是父,谁是子,然后让他们执行不同的代码片段

让我们来看一下fork的一般写法

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<unistd.h>4 5 int main()6 {7     printf("i am a process, 我的pid: %d\n", getpid());8 9 10     pid_t id = fork();11                                                                               12     if(id < 0) return 1;13 14     else if(id == 0)15     {16         // child17         while(1)18         {19             printf("我是子进程: pid: %d, ppid: %d, ret: %d, 我正在执行下载任务    \n",getpid(),getppid(),id);20             sleep(1);21         }22     }23 24     else25     {26         // parent27         while(1)28         {29             printf("我是父进程: pid: %d, ppid: %d, ret: %d, 我正在执行播放任务    \n",getpid(),getppid(),id);30             sleep(1);31         }32     }33 }

在这里插入图片描述
我们可以看到明明我们的fork只使用了一个变量接收但是出现了两个返回值

2.3 fork的原理

关于fork这个函数的原理,我们依然抛出几个问题

  1. fork干了什么事情?
  2. 为什么fork会有两个返回值?
  3. 为什么fork的两个返回值,会给父进程返回子进程pid,给子进程返回0?
  4. fork之后父子进程谁先运行?
  5. 如何理解同一个变量会有不同的值?

fork干了什么事情?

fork创建子进程,系统中会多一个子进程

  • 以父进程为模板,为子进程创建PCB
  • 但是你今天创建的子进程,是没有代码和数据的!!!目前和父进程共享代码和数据!!
  • 所以,fork之后,父子进程会执行一样的代码

在这里插入图片描述


为什么fork的两个返回值,会给父进程返回子进程pid,给子进程返回0?

在用进程中,一个父进程可能会有多个子进程,但是子进程永远都只有一个父进程,所以父 :子 只会是 1 :n,为了能够更好的管理这些子进程,就必须返回具有唯一性的pid。但是子进程会很容易找到父进程,所以返回0表示成功即可!!


fork之后父子进程到底谁先运行?

创建完成子进程,只是一个开始,创建完成子进程之后,系统的其他进程,父进程和子进程,接下来要被调度执行的,当父子进程的PCB都被创建并在运行队列中排队的时候,哪一个进程的PCB先被选择调度,那个进程就先运行!!

  • 但是PCB的选择调度是由操作系统自主决定(由各自PCB中的调度信息(时间片,优先级等)+调度器算法共同决定)
  • 所以我们不确定父子进程到底谁先运行

最后为什么fork会有两个返回值?

如果一个函数到达了return,那么他的核心工作是否完成?

  • 答案很显然是的,所以。。。

在这里插入图片描述
最后在fork之后代码共享,所以return也会被共享进入父子进程,并在父子进程中分别执行,所以在fork函数return之前,父子进程就已经分流,因此就会产生两个返回值!


如何理解同一个变量会有不同的值?

同一个函数有两个返回值是因为fork后两个进程都被调度了,但是同一个变量会有不同的值?该如何理解?

首先我们思考一下,如果我们杀掉子进程,父进程还会存在嘛?杀掉父进程呢?

分析父子进程是否独立

由此,我们可以得出结论:进程之间运行的时候,是具有独立性的,杀掉父进程不会影响子进程!反之也是!

  • 进程的独立性,首先是表现在有各自的PCB进行之间不会互相影响,代码本身是只读的,不会影响,数据父子是会修改的!代码共享,数据各个进程都会写时拷贝私有一份!
  • 变量id是父进程定义的变量,保存数据,返回的时候发生写时拷贝,不同
    的进程执行的代码中的变量id获取的值不同,所以id在父进程和子进程中值不同

3. 总结

fork函数的内容远不只有这么一点,但是理解这五个问题能快速帮助我们,简单理解这个函数,了解fork的原理!关于如何创建子进程我们就讲到这里!

谢谢大家支持本篇到这里就结束了
在这里插入图片描述


http://www.mrgr.cn/p/86863313

相关文章

IoTDB 入门教程③——基于Linux系统快速安装启动和上手

文章目录 一、前文二、下载三、解压四、上传五、启动六、执行七、停止八、参考 一、前文 IoTDB入门教程——导读 二、下载 下载二进制可运行程序&#xff1a;https://dlcdn.apache.org/iotdb/1.3.1/apache-iotdb-1.3.1-all-bin.zip 历史版本下载&#xff1a;https://archive.…

基于 Redis 发布订阅实现服务注册与发现

写在前面 其实很少有公司会使用 Redis 来实现服务注册与发现&#xff0c;通常是ETCD、NACOS、ZOOKEEPER等等&#xff0c;但是也不妨碍我们了解。本文会先介绍 Redis 的发布/订阅模式&#xff0c;接着基于这个模式实现服务注册与发现。 Redis发布订阅流程图&#xff1a; Red…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.4--汇编LED驱动程序

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

【MATLAB画图】如何绘制图像坐标系

首先我们需要图像坐标轴的原点在左上角&#xff1a; set(gca,ydir,reverse,xaxislocation,top); 然后我们需要坐标轴上加上箭头 quiver(0, 0, 0, 520); % 在(x1, y1)处绘制一个箭头&#xff0c;其方向和长度由(dx, dy)确定 quiver(0, 0, 700, 0); % 在(x1, y1)处绘制一个箭头…

嵌入式全栈开发学习笔记---C语言笔试复习大全3

目录 笔试题3 笔试题4 笔试题5 上一篇介绍了数据类型的长度和数据范围&#xff0c;并且分别讲解了两个经典的笔试题&#xff0c;这一篇我们再来看三道非常经典的考数据类型长度、数据范围和数据类型转换的笔试题。 说明&#xff1a;我们学过单片机的一般都是有C语言基础的了…

分布式与一致性协议之拜占庭将军问题(三)

拜占庭将军问题 叛将先发送消息 如果是叛将楚先发送作战消息&#xff0c;干扰作战计划&#xff0c;结果会有所不同吗&#xff1f; 在第一轮作战信息协商中&#xff0c;楚向苏秦发送作战指令"进攻",向齐、燕发送作战指令"撤退"&#xff0c;如图所示(当然还…

Seata AT模式学习

官方文档 Seata是目前国内最流行的一个分布式事务的组件,支持以下4种模式 AT模式:对业务代码无侵入,只要在业务的数据库加上一个UNDO_LOG表,在配置文件中配置好Seata的服务端,在需要开启全局事务的地方加上注解就行 TCC模式:即Try-Commit-Cancel,自定义prepare逻辑、com…

免费的单片机物联网MQTT平台选择

目的是多设备接入中控&#xff0c;平台只做转发。 选择巴法云&#xff1a;巴法科技&巴法云-巴法设备云-巴法物联网云平台 clientId是私钥uid&#xff1a; 多设备 clientId 填同一个 uid 都是可以的。平台应该是加了后缀区分。 支持自定义topic&#xff0c;操作简单&#x…

最好用的AI换脸软件,rope下载介绍(支持cpu)

随着AI技术的广泛运用,市面上的换脸软件也多了起来,今天给各位介绍其中的王者Rope! 先上两个动图,给大伙看看效果rope是如何实现这种自然的效果呢?这得益于机器学习技术的不断发展,rope经过深度神经网络的无数次迭代优化,最终得出的模型可以自动学习和识别视频中的人脸特…

Java中的IO流

IO流的概述和分类 IO流分为输入输出流 输入流&#xff1a;读数据 输出流&#xff1a;写数据 流&#xff1a;是一种抽象的概念&#xff0c;是对数据传输的总称&#xff0c;流的本质是数据传输 按照数据类型来分 字节流&#xff1a;字节输入流&#xff0c;字节输出流 字符…

​「Python大数据」词频数据渲染词云图导出HTML

前言 本文主要介绍通过python实现数据聚类、脚本开发、办公自动化。词频数据渲染词云图导出HTML。 一、业务逻辑 读取voc数据采集的数据批处理,使用jieba进行分词,去除停用词词频数据渲染词云图将可视化结果保存到HTML文件中二、具体产出 三、执行脚本 python wordCloud.p…

2024五一杯数学建模A题思路分析-钢板最优切割路径问题

文章目录 1 赛题选题分析 2 解题思路3 最新思路更新 1 赛题 A题 钢板最优切割路径问题 提高钢板下料切割过程中的工作效率&#xff0c;是模具加工企业降低成本和增加经济效益的重要途径&#xff0c;其中钢板切割的路径规划是钢板切割过程的一个关键环节。 钢板切割就是使用特殊…

随笔Ubuntu上的的一些使用

Ubuntu简易使用 常用指令 cdlsmkdirrf -rm 路径 换源 备份镜像 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak编辑文件设置 sudo gedit /etc/apt/sources.list清华源 # 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe mul…

提高学生学习成绩和自我效能感:护理培训的移动聊天机器人方法

(Promoting students learning achievement and self-efficacy: A mobile chatbot approach for nursing training) DOI: 10.1111/bjet.13158 一、摘要 研究目的:护理培训的目的不仅在于掌握技能,更在于培养解决问题的决策能力。然而,产科疫苗接种知识等培训项目大多采用以讲…

STM32 F103C8T6学习笔记16:1.3寸OLED的驱动显示日历

今天尝试使用STM32 F103C8T6驱动显示 1.3寸的OLED&#xff0c;显示数字、字符串、汉字、图片等 本质与0.96寸的OLED是完全相同的原理&#xff1a; 而且经过我的研究发现: 1.3寸大小的OLED并未比0.96寸的有更多的显示像素点数来显示&#xff0c;也是128*64的像素点数显示: 也…

【记录】Springboot项目集成docker实现一键部署

公司管理平台完成后&#xff0c;为了方便其他不懂开发的同事部署和测试&#xff0c;集成docker进行一键部署&#xff0c;也为后面自动化部署做准备。本文做个简单记录。 1、安装docker yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/cont…

ESXI上安装和使用MegaCli

一、下载安装包 目前官网找不到安装包了,这里提供一个MegaCli-8.04.07:https://www.lanzoub.com/iUzBn1tyhdxi 二、将安装包解压上传到esxi 可以通过sftp或者其他工具上传到esxi中,不太建议在esxi上直接下载,我提供的是rar压缩包。这里我使用WinSCP工具上传到esxi中,下载地…

图像处理的一些操作(1)

图像处理 1.安装PIL&#xff0c;skimage库1.1导入skimage库中的oi模块和data模块 2.读取图像文件2.1读取图像文件2.2 以灰度模式读取图像2.3 查看示例图像的目录路径2.4 读取chelsea图片2.5 加载示例图片并保存2.6 获得加载图片的信息2.6.1 输出图片类型2.6.2 输出图片尺寸2.6.…

Qwen-Audio:推动通用音频理解的统一大规模音频-语言模型(开源)

随着人工智能技术的不断进步&#xff0c;音频语言模型&#xff08;Audio-Language Models&#xff09;在人机交互领域变得越来越重要。然而&#xff0c;由于缺乏能够处理多样化音频类型和任务的预训练模型&#xff0c;该领域的进展受到了限制。为了克服这一挑战&#xff0c;研究…

装备购买

解释一下蓝书上的做法 按照数学归纳法证明这个贪心,假设当前在第\(i\)行,前面已经选出\(i-1\)个线性无关的向量了(非零行),那么对于这一行,如果最终的结果不选\(z[k]\),而是选了另一个\(z[l]\),那么最终的向量组加入\(z[k]\)后就线性相关了,\(z[k]\)可以被这个向量组唯…