一文初识Linux进程(超详细!)

                                                          🎬慕斯主页修仙—别有洞天

                                                         ♈️今日夜电波:HEART BEAT—YOASOBI

                                                                2:20━━━━━━️💟──────── 5:35
                                                                    🔄   ◀️   ⏸   ▶️    ☰  

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

如何查看进程?

方法一

方法二

如何理解进程?

创建子进程—fork()

如何理解子进程的创建?

如何理解fork()会有两个返回值?

进程之间的独立性如何保证?

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


如何查看进程?

方法一
ps ajx | head -1 && ps ajx | grep 执行程序的名字 | grep -v grep

对于以上指令的解析:

ps ajx 查看当前系统中所有的进程

| 管道 在使用管道符 "|" 时, "|" 左边的进程以写的方式打开管道文件,将标准输出重定向到管道之中, "|" 右边的进程以读的方式打开管道文件,将标准输入重定向到管道之中。

head -1 用于只查看第一行的命令

grep 执行程序的名字 查看对应名字的执行程序

grep -v 执行程序的名字 将除了-v 后面的执行程序的内容都显示出来

显示效果如下:

方法二
ls /proc

        该指令用于查看进程相关的属性,可以根据是否有对应程序的pid来判断是否有该进程。通过以下的指令可查看对应进程的详细属性:

ls /proc/进程pid

        也可通过后面加上 -d 或者 -l 指令用于查看对应目录和详细信息

如何理解进程?

创建子进程—fork()

        启动一个进程,如何理解这种行为?本质就是多了一个进程,操作系统管理的进程也就多了一个,进程=可执行程序+task_struct对象(内核对象)。

        创建一个进程,就是系统中要申请内存,保存当前进程的可执行程序+task_struct对象,并将task_struct对像添加到进程的列表中。

        通过fork()创建子进程,当使用fork()后程序会出现两个执行流,分别为一个父进程的执行流还有一个子进程的执行流,看如下例子:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>int main()
{printf("i am a father process,pid:%d ppid:%d\n",getpid(),getppid());fork();while(1){printf("i am a process,pid:%d ppid:%d\n",getpid(),getppid());                                                                                                                        sleep(1);}return 0;
}

        可以看到如上的效果,我们也可以得出一个结论:fork()之前的代码只有父进程会执行,而fork()之后的代码则是父子进程都要执行。

        需要注意的是fork()有返回值,当我们fork()成功时会返回两个不同的返回值,子进程会返回0,父进程会返回子进程的pid,创建失败则会返回-1。对此我们可以通过判断返回值来执行不同的代码片段!如下代码:

   #include<stdio.h>#include<unistd.h>#include<sys/types.h>int main(){pid_t cg=fork();if(cg==0){printf("i am son process: mypid:%d my forkrt:%d \n",getpid(),cg);}if(cg>0){printf("i am father process: mypid:%d my forkrt:%d \n",getpid(),cg);                                                                                                             }return 0;}

        看到这里你可能会很奇怪,为什么两段程序的执行顺序对不上呢,不是应该先执行son再执行father吗?实际上父进程和子进程是有各自PCB中的调度信息以及调度算法共同决定的!我们不能确定哪一段代码片段先运行!谁先运行主要还是靠调度器来决定!

如何理解子进程的创建?

        我们都知道进程=可执行程序+task_struct对象,那么fork创建了一个字进程,系统就会多一个进程,也就是我们的内存中会多一个进程。

        而对于子进程的创建会以父进程为模板创建子进程的PCB,这个PCB会拷贝大部分的基础属性,但是小部分是不同的,比如pid、ppid等等。

        但是,在PCB创建后子进程是没有可执行程序(也就是代码和数据)的,因此,在fork()后,子进程会和父进程共享代码和数据!当然后面数据是可能会各自独立出来一份的!一图让你了解:

如何理解fork()会有两个返回值?

        通过上面的理解,我们都知道fork()过后会创建子进程,那么在创建子进程后,父进程和子进程会对代码+数据进行共享。那么也就是说我们的 return 也共享了!因为 return 也是代码啊!所以父进程被调度 会执行return,子进程被调度 也会执行 return!

而实际上,操作系统是通过一些寄存器做到返回值返回两次!

进程之间的独立性如何保证?

        进程之间运行的时候,具有独立性,无论是什么关系!

        进程的独立性,首先表现在各自的PCB。

        进程之不会互相影响!代码本身是只读的,不会影响!但是数据父子是会修改的!

当我们对于一个进程的数据进行修改时,你会发现另外一个进程没有发生改变,这是因为操作系统触发了写时拷贝,确保了每一个进程的数据的独立性。

        那什么是写实拷贝呢?

        由于fork()后代码共享,对于数据各个进程必须想办法各自私有一份。对此,我们可以理解为C++中的浅拷贝以及深拷贝,对于刚刚开始fork()则是浅拷贝,共享数据和代码。当父或者子要进行修改时,我们就要实现两者的区分,要进行深拷贝。

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

        对于fork()进行完后会进行return,也就是fork()函数的返回值。在程序运行到返回时,说明他的程序已经基本完成了,而返回的本质是写入,在返回的时候发生了写实拷贝,对于进程会有各自的数据,所以同一个变量会有不同的值!


                    感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                         给个三连再走嘛~  

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据转换的三剑客:Pandas 中 apply、map 和 applymap 方法的应用指南

数据转换的三剑客&#xff1a;Pandas 中 apply、map 和 applymap 方法的应用指南 ​ 在 Pandas 中&#xff0c;apply、map 和 applymap 是常用的数据转换和处理方法&#xff0c;它们为数据分析和数据处理提供了灵活的功能。这些方法可以根据具体的需求选择合适的方法进行操作。…

异常控制流ECF

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/jintongxu。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 一、异常控制流&#xff08;ECF) 现代…

字符串转成时间的SQL,一个多种数据库通用的函数

select date 2010-10-06 from dual; date 函数&#xff0c;此函数适用于&#xff1a; 1.MySQL数据库 2.Oracle数据库 3.达梦数据库 4.人大金仓数据库

生存分析survival_analysis_COXmodel_python实现

什么是生存分析&#xff1f; 生存分析&#xff08;在工程中也称为可靠性分析&#xff09;的目标是建立协变量与事件发生时间之间的联系。该算法起源于临床医学研究&#xff0c;往往主要目标是预测死亡时间&#xff0c;即生存。生存分析是一种回归问题&#xff08;人们想要预测…

如何让GPT成为你的科研助手?

如何让GPT成为你的科研助手&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定制自己的GPTs 1.自定义GPTs使…

深度学习中氨基酸序列的编码方法

目录 1. 常规特征编码方法1.1 类别特征1.2 文本特征 2. 基于领域先验知识的编码方法2.1 演化关系2.2 理化性质 3. 基于学习的编码方法3.1 预训练模型3.2 端到端方法 参考 随着AI算法创新和算力提升&#xff0c;叠加生物&#xff08;组学&#xff09;数据&#xff08;指数级&…

C语言注意点(1)

1、switch&#xff0c;case&#xff0c;break&#xff0c;default相关注意点 当变量表达式的内容与某个case后的常量相等后&#xff0c;就执行该case下的语句&#xff0c;break表示该case以后的内容不会执行(立即跳出switch语句)&#xff0c; 如果没有跟break&#xff0c;会继续…

C++正则表达式全攻略:从基础到高级应用

C正则表达式全攻略&#xff1a;从基础到高级应用 一、基础知识二、正则表达式的基本匹配三、C中使用正则表达式四、高级正则表达式五、实践示例六、性能优化6.1、编译正则表达式6.2、避免过度使用回溯6.3、优化匹配算法 七、总结 一、基础知识 正则表达式是一种用于匹配、搜索…

国标GB28181对接的时候如何配置服务端口和本地端口

目 录 一、国标GB28181对接需要配置的端口等参数 二、GB28181服务器端口的配置&#xff1a;SIP服务器端口 三、GB28181设备测端口的配置&#xff1a;本地SIP端口 &#xff08;一&#xff09;本地SIP端口配置的意义 &#xff08;二&#xf…

<软考高项备考>《论文专题 - 42 范围管理(1) 》

1 范围管理基础 1.1 写作要点 过程定义、作用写作要点、思路规划范围管理规划范围管理是为了记录如何定义、确认和控制项目范围及产品范围&#xff0c;而创建范围管理计划的过程。作用:在整个项目期间对如何管理范围提供指南和方向。写范围管理计划、需求管理计划的内容;编写…

翼辉 SylixOS 正式支持“申威“处理器架构

近日&#xff0c;翼辉信息发布了最新的 SylixOS V3.4.0 操作系统。在 SylixOS V3.4.0 中&#xff0c;已正式加入了对申威 SW64 自主指令集架构的支持。 SW64 自主指令集架构是我国在处理器领域的一项重要突破&#xff0c;其知识产权完全可控、自主性高、安全性强&#xff0c;核…

深度学习|10.2 边缘检测示例 10.3 更多边缘检测

文章目录 如何在编程中实现卷积运算使用卷积实现边缘检测结果矩阵的元素正负性质的意义水平分类器如何构造卷积运算使用的矩阵 原矩阵通过一个过滤器&#xff08;filter&#xff09;/核心&#xff08;kernel&#xff09;来生成一个新的矩阵。 如何在编程中实现卷积运算 使用卷积…