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

前言:在上一篇文章中,我们已经会使用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         // child
 17         while(1)
 18         {
 19             printf("我是子进程: pid: %d, ppid: %d, ret: %d, 我正在执行下载任务    \n",getpid(),getppid(),id);
 20             sleep(1);
 21         }
 22     }
 23 
 24     else
 25     {
 26         // parent
 27         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的原理!关于如何创建子进程我们就讲到这里!

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

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

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

相关文章

【华为】路由综合实验(基础)

【华为】路由综合实验 实验需求拓扑配置AR1AR2AR3AR4AR5PC1PC2 查看通信OSPF邻居OSPF路由表 BGPBGP邻居BGP 路由表 配置文档 实验需求 ① 自行规划IP地址 ② 在区域1里面 启用OSPF ③ 在区域1和区域2 启用BGP&#xff0c;使AR4和AR3成为eBGP&#xff0c;AR4和AR5成为iBGP对等体…

buuctf-misc-22.神秘龙卷风1

22.神秘龙卷风1 题目&#xff1a;暴力破解-翻译Brainfuck计算机语言 根据提示是4位密码&#xff0c;直接破解密码即可 解压后发现是这样一个文档 我们尝试使用网站翻译这个 内容由“”、“.”、“>”三种符号组成&#xff0c;我刚开始认为这是一种密文&#xff0c;经过搜索…

thinkpad电脑文件隐藏了怎么恢复?教你几招

在使用ThinkPad电脑时&#xff0c;有时我们可能会发现一些文件或文件夹突然“消失”了&#xff0c;这通常是因为它们被隐藏了。本文将为您介绍几招恢复ThinkPad电脑上隐藏文件的方法&#xff0c;帮助您轻松找回丢失的文件。 图片来源于网络&#xff0c;如有侵权请告知 一、了解…

【实时数仓架构】方法论

笔者不是专业的实时数仓架构&#xff0c;这是笔者从其他人经验和网上资料整理而来&#xff0c;仅供参考。写此文章意义&#xff0c;加深对实时数仓理解。 一、实时数仓架构技术演进 1.1 四种架构演进 1&#xff09;离线大数据架构 一种批处理离线数据分析架构&#xff0c;…

when to create a ViewRootImpl

when to create a ViewRootImpl when method setView is called: when method dispatchDetachedFromWindow is called:

预训练模型介绍

一、什么是GPT GPT 是由人工智能研究实验室 OpenAI 在2022年11月30日发布的全新聊天机器人模型, 一款人工智能技术驱动的自然语言处理工具 它能够通过学习和理解人类的语言来进行对话, 还能根据聊天的上下文进行互动,能完成撰写邮件、视频脚本、文案、翻译、代码等任务 二、 为…

TypeScript学习笔记:迈向更安全的JavaScript编程

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux专栏05:Linux基本指令之目录处理指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之目录处理指令 编号&#xff1a;05 文章目录 Linux基…

STM32之HAL开发——电容按键

电容按键原理 电容器 (简称为电容) 就是可以容纳电荷的器件&#xff0c;两个金属块中间隔一层绝缘体就可以构成一个最简单的电容。如图 32_1 (俯视图)&#xff0c;有两个金属片&#xff0c;之间有一个绝缘介质&#xff0c;这样就构成了一个电容。这样一个电容在电路板上非常容…

线程同步与条件变量

再论生产消费者问题 问题 如果缓冲池为空&#xff0c;如何定义消费者的行为? 一种可能的解决方案 这种方案是可行的&#xff0c;但是如果生产者一直不生产&#xff0c;那么消费者会反复查看产品的数量为 0 并休眠&#xff0c;这样会浪费 cpu 的资源&#xff0c;并且生产者生产…

MWCNTs微纳米纤维膜的制备

MWCNTs微纳米纤维膜是一种由多壁碳纳米管&#xff08;MWCNTs&#xff09;与聚合物纤维复合而成的纳米纤维膜。这种材料结合了MWCNTs的良好性能和纳米纤维膜的高比表面积、高通量等特点&#xff0c;具有广泛的应用前景。 在制备过程中&#xff0c;首先需要对MWCNTs进行酸化处理和…

基于SpringBoot的私人健身与教练预约管理系统设计与实现

一、引言 私人健身与教练预约管理系统&#xff0c;可以摆脱传统手写记录的管理模式。利用计算机系统&#xff0c;进行用户信息、管理员信息的管理&#xff0c;其中包含首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;教练管理&#xff0c;健身项目管理&#xff0c;项…

Agent AI智能体:如何借助机器学习引领科技新潮流

文章目录 &#x1f4d1;前言一、Agent AI智能体的基本概念二、Agent AI智能体的技术进步2.1 机器学习技术2.2 自适应技术2.3 分布式计算与云计算 三、Agent AI智能体的知识积累3.1 知识图谱3.2 迁移学习 四、Agent AI智能体的挑战与机遇4.1 挑战4.2 机遇 小结 &#x1f4d1;前言…

Linux下安装snaphu

1、官网下载安装包 2、解压&#xff0c;移动文件夹到/usr/local/下 3、在/usr/local/下创建man&#xff0c;在man下创建man1文件夹 4、进入到snaphu的src文件夹里&#xff0c;执行sudo make&#xff0c;如果报错 在这个 Makefile 中&#xff0c;-arch x86_64 是 macOS 特定的…

小区服务|基于SprinBoot+vue的小区服务管理系统(源码+数据库+文档)

目录 基于SprinBootvue的小区服务管理系统 一、前言 二、系统设计 三、系统功能设计 1管理员登录 2 客服聊天管理、反馈管理管理 3 公告信息管理 4公告类型管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博…

图论之最短路算法模板总结

来个大致的分类&#xff1a; 朴素的迪杰斯特拉&#xff1a; 实现&#xff1a; 我们让s表示当前已经确定的最短距离的点&#xff0c;我们找到一个不在s中的距离最近的点t&#xff0c;并用t来更新其他的点。 下面是AC代码&#xff1a; #include<bits/stdc.h> using nam…

《Spring-MVC》系列文章目录

简介 Spring MVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;它通过把Model&#xff08;模型&#xff09;、View&#xff08;视图&#xff09;、Controller&#xff08;控制器&#xff09;分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂…

Getting started - 英文版 - English Version

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace This pa…

在不同操作系统上自动生成Protocol Buffers的Java语言包的方法

各语言的Protocol Buffers文件都需要通过protoc来生成&#xff0c;这个动作往往需要手动输入命令完成。本文介绍的方法&#xff0c;将借助Maven来实现自动化生成工作。这样开发者只要专注于proto的定义&#xff0c;且不用将生成的文件上传到代码仓库&#xff0c;从而降低开发的…

Tracecat:开源 SOAR

Tracecat 是一个面向安全团队的开源自动化平台。 开发人员认为&#xff0c;每个人都应该可以使用安全自动化&#xff0c;特别是人手不足的中小型团队。 核心功能、用户界面和日常工作流程基于一流安全团队的现有最佳实践。 使用专门的人工智能模型来标记、总结和丰富警报。 …