[Linux进程(一)] 什么是进程?PCB的底层是什么?以及进程标识符pid与ppid

在这里插入图片描述

文章目录

  • 1、前言
  • 2、描述进程 — PCB(os怎么管理进程呢)
  • 3、查看进程
    • 3.1 方法一
    • 3.2 方法二
  • 4、系统调用获取进程标示符(PID)
    • 4.1 获取进程的ID
    • 4.2 获取进程的父进程ID
  • 5、系统调用创建子进程-fork

1、前言

大家经常都在讲进程,而它到底是什么呢?
这里给大家先简单的介绍一下:

  • 课本概念:程序的一个执行实例,正在执行的程序等。
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体。

2、描述进程 — PCB(os怎么管理进程呢)

在操作系统中我们说到,os管理的本质并不是对事物本体的管理,而是对数据的管理。
这里虽然我们并不知道进程是什么,但是按照上面的理解,我们对进程的管理,也是对进程的数据进行管理,这里就用到那六个字“先描述,再组织”。我们来画图理解一下:
在这里插入图片描述
操作系统可能会同时管理非常多的“进程”,因此在管理的时候,管理这些进程的数据即可,将这些进程共有的属性提取出来,用结构体将其存起来,再使用链表将其链接起来,这样就能有效的管理进程,这样的机制就叫做“先描述,再组织”。
这个进程属性的集合就叫做PCB,也叫做进程控制块。
PCB是一个统称,在Linux中,PCB叫做 task_struct。
最终,我们操作系统对PCB的管理就被建模成了对链表的增删查改。
我们得出:进程 = 可执行程序 + 内核数据结构

3、查看进程

3.1 方法一

在Linux下我们可以使用下面的这个命令来查看进程:

ps ajx

在这里插入图片描述
这是所有的进程,如果我们只是对其中一个进程查看呢?我们看下面的:
我们先写一段C语言程序,编译为可执行程序并执行,然后使用该命令来查看一下进程:

#include <stdio.h>
#include <unistd.h>int main()
{while(1){printf("我是一个进程\n");sleep(1);}return 0;
}

在这里插入图片描述
命令:

ps ajx | grep mycode

这里用到我们以前学到的 管道符与过滤,筛选出我们想找的进程。

3.2 方法二

我们可以通过根目录下的proc目录来查看。proc目录下保存有进程的信息。
在这里插入图片描述

proc目录下的蓝色数字就是每一个进程的pid(Process ID),这就跟我们的身份证号一样,一人只有一个,每个进程都只有这么一个标识符。
我们再次以刚才那段C语言为例,来查看进程:
在这里插入图片描述
在这里插入图片描述
如果我们删掉磁盘上可执行程序,进程没有终止的话,我们仍然是可以查到的,因为进程是程序拷贝到内存中的,代码+数据都被拷贝下来了,所以删掉磁盘上的可执行程序不会影响的。
在这里插入图片描述
当终止掉程序,内存中拷贝的可执行程序与数据都被释放掉了,因此再去查就查不出来了。
在这里插入图片描述

4、系统调用获取进程标示符(PID)

  • 进程id(PID)
  • 父进程id(PPID)
    我们在上面使用 ps ajx 命令的时候发现,有一个PID,还有一个PPID,我们不难猜到,这些都是PCB中的属性。
    如果获取呢?这里要介绍我们第一个要学习系统调用,getpid与getppid了。我们使用man手册查一下看看怎么说。
    在这里插入图片描述
    我们接下来就使用getpid与getppid系统调用接口来看看能不能查到pid与ppid。

4.1 获取进程的ID

这里我们写一段C语言程序来调用看看:

#include <stdio.h>                     
#include <sys/types.h>                  
#include <unistd.h>                    int main()                                                                          
{                                                                                   while(1)                                                                        {                                                                               printf("我是一个进程,pid = %d\n", getpid());                                                                            sleep(1);                                                          }return 0;                       
} 

编译后我们运行可执行程序,并使用下面 ps ajx 命令来对比看,pid是否正确。

ps ajx | head -1 && ps ajx | grep mycode | grep -v grep

在这里插入图片描述
我们发现,getpid确实是没错的,并且我们调用是没有出错的。
当我们想要终止掉一个进程的时候,我们总是用 ctrl + c,今天我们再来学一个终止命令,kill 命令。

kill -9 pid  // 这里的9是9号信号

在这里插入图片描述

4.2 获取进程的父进程ID

我们继续改写上面的C语言代码,再来看看 getppid() 系统调用接口。

#include <stdio.h>                     
#include <sys/types.h>                  
#include <unistd.h>                    int main()                                                                          
{                                                                                   while(1)                                                                        {                                                                               printf("我是一个进程,pid = %d, ppid = %d\n", getpid(), getppid());                                                                            sleep(1);                                                          }return 0;                       
} 

在这里插入图片描述
经过我的不断调用发现,每次运行pid都是在变化的,但是ppid确实一直没有变化,我猜它是一直在运行的,我们来查看一下它是谁。
在这里插入图片描述
原来它是命令行解释器 bash 呀。我们由此也知道了,我们所敲出来的命令都是 bash 的子进程。
那我们Linu下有没有创建子进程的系统接口呢,有,我们再来学一下。

5、系统调用创建子进程-fork

我们可以使用fork创建子进程,先查一下man手册看看:
在这里插入图片描述
我们写一份 C语言代码来试着调用系统接口 fork()。
我们先想一下,我们有自己的进程为什么还要去创建子进程呢?
在上面的学习我们看到,我们输入的命令是执行命令得到结果,而父进程bash是解释你所输入的命令,这就说明,我们父子进程各自做各自的事。由此,我们想是不是可以,按照fork的返回值配合 if-else 语句来执行不同的事。我们试一下:

#include <stdio.h>
#include <unistd.h>int main()
{printf("我是一个父进程,我的pid:%d\n", getpid());pid_t id = fork();// fork之后用if分流if(id < 0) return -1;else if(id == 0){// childwhile(1){                printf("我是子进程,pid:%d, ppid:%d\n", getpid(), getppid());sleep(1);                                                             }}else {// parentwhile(1){printf("我是父进程,pid:%d, ppid:%d\n", getpid(), getppid());sleep(1);}}return 0;
}

我们编译后运行可执行程序。
在这里插入图片描述

通过打印出来的结果,我们发现刚我们的猜测是正确的!!!
这里我们可以总结出几个问题,对fork作以总结:
1、fork干了什么事情?
调用fork()后,创建了子进程,父子进程可以协作,干不同的事。
2、为什么fork会有两个返回值?
我们在查文档的时候,就有返回值的介绍。
成功时,给父进程返回子进程的pid,给子进程返回0;失败时,给父进程返回-1,不创建子进程。
fork之后代码共享,fork函数执行两次就有两个返回值,一次返回父进程接收,另外一次返回子进程接收。
3、为什么fork的两个返回值,会给父进程返回子进程pid,给子进程返回0?
我们与现实生活联系起来。现实中,父 : 子 = 1 : n(n >= 1),父亲给孩子不同名字,可以更好的区分孩子(保证唯一性)。这样类比到这里,给父进程返回子进程的pid,父进程必须有标识子进程的方式,而子进程只需要知道自己是否被创建成功,以及知道父进程是谁即可 (调用 getppid())。
4、fork之后谁先运行?
我们上面运行了可执行程序后,发现先跑了父进程的代码片段,然后跑子进程的代码片段,但是后面并不是这样的规律。
当创建完子进程后,系统的其他进程,以及父进程和子进程都要被调度。父子进程的PCB都被创建并在运行队列中排队,哪个进程的PCB先被调度,哪个进程就先被运行,是由操作系统决定的,不确定的。
5、如何理解同一个id变量,怎么会有不同的值?
当父子进程都被运行时,他们共用一份代码与数据,但是一旦发生数据的写入,就会发生写时拷贝,数据就不再共享,而是父子进程各一份自己的数据,因此就会出现同一个变量,值不相同。

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

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

相关文章

2015年电赛控制类—STM32风力摆控制系统资料+源程序

目录 一、项目背景 二、主要研究内容 三、总体思路与研究方案 四、主要研究结果 五、程序 六、图片 一、项目背景 风力摆控制系统是一种利用风力控制物体做简谐运动的系统&#xff0c;风力的利用和控制技术在我国的发展尚未完善&#xff0c;国内正处于起步阶段。风力摆的…

用React给XXL-JOB开发一个新皮肤(二):目录规划和路由初始化

目录 一. 简述二. 目录规划三. Vite 配置 3.1. 配置路径别名3.2. 配置 less 四. 页面 4.1. 入口文件4.2. 骨架文件4.3. 普通页面 五. 路由配置六. 预览启动 一. 简述 上一篇文章我们介绍了项目初始化&#xff0c;此篇文章我们会先介绍下当前项目的目录规划&#xff0c;接着对…

Java网络爬虫--HttpClient

目录标题 技术介绍有什么优点&#xff1f;怎么在项目中引入&#xff1f; 请求URLEntityUtils 类GET请求带参数的GET请求POST请求 总结 技术介绍 HttpClient 是 Apache Jakarta Common 下的子项目&#xff0c;用来提供高效的、功能丰富的、支持 HTTP 协议的客户端编程工具包。相…

【沉淀之华】SpringBoot配置原生HikariCP数据源两次初始化过程剖析 服务器与本地完全一致却不同数据源结果定位

文章目录 背景介绍场景复现溯源彩蛋 背景介绍 JDK版本&#xff1a;1.8 SpringBoot&#xff1a; 2.2.3.RELEASE 整合原生Hikari数据源连接池 IDEA&#xff1a;2023.1 再保证服务器和本地的启动参数、apollo配置、代码分支完全一致的前提下&#xff0c;经过验证得到如下结论 在…

【ITK库学习】使用itk库进行图像分割(四):水平集分割

目录 1、水平集2、itkFastMarchingImageFilter 快速步进分割3、itkShapeDetectionLevelSetImageFilter 快速步进分割 1、水平集 水平集是跟踪轮廓和表面运动的一种数字化方法。基于图像的亮度均值、梯度、边缘特征的微分计算&#xff0c;进行水平集分割。在itk中&#xff0c;所…

一台Linux服务jdk1.6 与 jdk1.8 并存,tomcat6+tomcat8 并存

Linux jdk1.6,1.8 tomcat6 tomcat8 并存 需求场景&#xff1a; 有一个项目 原来是 jdk1.6tomcat6 部署的&#xff0c;现在需要进行项目架构升级 项目需要适配jdk1.8 然后用 jdk.8 tomcat 8进行部署&#xff0c;然后下架 jdk1.6 的linux服务 现在有一台 jdk.8 tomcat 8的linu…

debug OpenBLAS library 和 应用示例

1. 构建openblas lib git clone gitgithub.com:OpenMathLib/OpenBLAS.git cd OpenBLAS/ 如果要安装在自定义文件夹中&#xff0c;可以修改 PREFIX 的定义&#xff1a; 将 PREFIX /opt/OpenBLAS 修改成 PREFIX ../local/ 然后构建&#xff1a; make -j make install 如果要…

抽烟识别摄像机

抽烟识别摄像机是一种利用计算机视觉和人工智能技术的设备&#xff0c;能够实时监测和识别吸烟行为。该摄像机通过分析人体姿态和动作&#xff0c;识别出可能的吸烟行为&#xff0c;并及时发出警告或报警。这种摄像机可以广泛应用于公共场所、办公场所、学校和医疗机构等地方&a…

仰望星空,也要鲜花与掌声

在各种武侠文化的渲染下&#xff0c;我从小萌生了一种奇怪的想法&#xff0c;就是弄任何事都要偷偷摸摸的钻研&#xff0c;最后惊艳所有人&#xff1b;因此无论是大学还是毕业工作中&#xff0c;很多事情都希望做到“完美”再同步给“外界”&#xff0c;如以下几个例子 学习Sp…

vue element plus Typography 排版

我们对字体进行统一规范&#xff0c;力求在各个操作系统下都有最佳展示效果。 字体# 字号# LevelFont SizeDemoSupplementary text12px Extra SmallBuild with ElementBody (small)13px SmallBuild with ElementBody14px BaseBuild with ElementSmall Title16px MediumBuild w…

恭喜Zhilong LI同学通过Oracle 19c OCP考试

Oracle 19c OCP两门科目考试成绩、证书展示&#xff1a; Oracle 19c OCP 1z0-082考试详情 Oracle 19c OCP 1z0-083考试详情

vue element plus 安装

环境支持# Element Plus 可以在支持 ES2018 和 ResizeObserver 的浏览器上运行。 如果您确实需要支持旧版本的浏览器&#xff0c;请自行添加 Babel 和相应的 Polyfill 。 由于 Vue 3 不再支持 IE11&#xff0c;Element Plus 也不再支持 IE 浏览器。 Edge ≥ 79Firefox ≥ 78C…