【Linux系统编程】进程概念详解(什么是进程?如何查看进程?)

目录

一、前言

二、 什么是进程?

💦引出进程 

💦进程的基本概念

💦理解进程 

⭐描述进程--PCB(进程控制块)

⭐组织进程

三、查看进程 

💦 通过 ps 命令查看进程 

 💦 通过 ls / proc  命令查看进程 

 💦通过系统调用获取进程标示符

四、共勉 


一、前言

        在学习了【Linux系统编程】中的  操作系统 和  冯·诺依曼体系结构 之后,我们已经对系统应该有了不错的了解,接下里我们将继续深入的了解操作系统最重要的的功能之一:进程管理

        那么操作系统是如何进行进程管理的呢?------很简单,先把进程描述起来再把进程组织起来!

        那么进程又是什么呢?------所以本次博客将从进程讲起!

二、 什么是进程?

💦引出进程 

 首先我们来看一个问题:

 操作系统能不能一次运行多个程序呢?---------当然可以啦!!

  • 因为运行的程序有很多,所以 OS 需要将这些运行的程序管理起来

我们将这些正在运行的程序称之为进程。(注意:是正在运行的程序叫进程,而不是程序本身)

  • 如何管理这些进程呢?—— 先描述,再组织!
  • 操作系统会创建一个描述和控制该进程的结构体。这个结构体称之为进程控制块(PCB,Processing Control Block),里面包含了该进程几乎所有的属性信息,同时通过进程控制块也可以找到该进程的代码和数据。
  • 在 Linux 中,进程控制块就是 struct task_struct 结构体。
  • 描述好所有进程了,还需要将所有进程的 PCB 给组织起来(通过双链表的方式),此时操作系统只需要拿到双链表的头指针,就可以找到所有进程的 PCB。
  • OS 把对进程的管理就转换成了,对数据结构中 PCB 的管理,即对双链表的增删查改操作。

   

假设这里有一个可执行程序 test它存储在磁盘上,就是一个普通文件,当我们 ./test 运行此程序,操作系统会做以下事情:将该程序从磁盘加载到内存中,并为该程序创建对应的进程,申请进程控制块(PCB)。


总结

  1. 为什么要存在 PCB 呢?—— 因为 OS 要对进程进行管理。

  2. 目前对于进程的理解:进程 = 程序(代码 + 数据) + 内核申请的与该进程对应的数据结构(PCB)

💦进程的基本概念

首先读者要知道的是,什么是进程?

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

        对于课本中的观点大家可能会觉得难以理解,为何正在执行的程序就是一个进程呢。我们可以在Windows下按[Ctrl + shift + ESC]打开任务管理器查看一下:

       可以看到左上角的这个【进程】标志,代表呢我们下面所运行的程序都是一个进程

👉 这也就表明了在一个操作系统中不仅只能运行一个进程,还可以运行多个进程

但是呢,进程不仅仅可以像上面这样去理解。我们来思考一个问题:程序是文件吗?

  • 相信读者肯定很清楚,文件是存放在磁盘中的,磁盘呢则是属于外设。这一块我们在冯·诺依曼体系结构有讲得很清楚,对于CPU来说,它是只会和内存打交到的,所以磁盘中的数据需要先加载到内存中才可以被执行

 那么,当可执行文件被加载到内存中时,该程序就成为了一个【进程】


总结:

进程 = 程序(代码 + 数据) + 内核申请的与该进程对应的数据结构(PCB)
 

💦理解进程 

 在了解了进程的基本概念后,我们来更加进一步地认识一下进程管理是如何实现的?

  • 那肯定是---- 先描述进程----在组织进程

⭐描述进程--PCB(进程控制块)

 首先读者要清楚我们是怎么辨别一个事物的:没错,就是通过其各种属性

       那么在 Linux 中,我们使用一个结构体去描述一个进程,因为 Linux 的内核源代码都是使用C语言来写的,而 结构体 则是C语言里面的一些知识,不懂的同学可以先去了解一下。并且呢这个结构体还有名字的,它叫做【进程控制块】----- PCB

  • 课本中的叫法呢是:PCB(Process Control Block)
  • Linux操作系统下的PCB是:task_struct

这个结构体呢就是组织了各种各样的属性,才可以去很好地描述一个进程


以下就是这个task_struct的所有结构信息:(后续我们会逐一讲解!)

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息

转换为代码形式的话就可以是下面这样

struct PCB{
	进程的编号
    进程的状态
    进程的优先级
    ...
    相关的指针信息
};

既然知道了如何去描述一个PCB结构体,我们就要来知道操作系统对一个进程总共会做哪些事情

  1. 为该进程创建对应的PCB对象
  2. 将该进程的代码和数据加载到内存中

  • 所以,很多教科书在介绍进程的时候只会说它在计算机内部是一个PCB对象,其实对于一个进程来说:应该是由操作系统为其创建出来的 PCB对象 + 其数据代码 组成的

总结:

👉 【进程】 = 内核PCB数据结构对象(描述你这个进程所有的属性值) + 你自己的代码和数据(在磁盘当中所形成的可执行程序)

⭐组织进程

        上面谈到了操作系统如何利用PCB去描述一个相关的进程,接下去我们来说说如何去组织进程

         大学的校园我们都知道,比中学的大多了。但是呢在学校里每个学生他的人身是自由的,不可能每个人拿着一个牌子,上面自己写上个人的基本信息,这是不现实的。比方说学院的辅导员想要找一个学生的话,一定是通过在学籍系统中找到这个学生的所在行记录,才可以对其进行相关的操作,读者可以认为这个信息记录即为我们在上面所讲到的【PCB对象】
         因此操作系统如果要去管理一个进程的话只需要找到某个进程的PCB对象即可,通过这个PCB对象就可以找到相对应的代码和数据

  • 那这个PCB结构体中就一定存在一个东西叫做结构体指针,里面保存了某个内容的地址,方便我们很快地知道其它对应的PCB信息
struct PCB{
	进程的编号
    进程的状态
    进程的优先级
    ...
    相关的指针信息
    struct PCB* next;
};

这样可能还是抽象了一点,我们再举个形象点的案例 

  • 读者可能是在校大学生,亦或者是已经工作的人。但是无论是谁都要去投递简历找工作。如果读者有当过面试官的话一定可以知道每天公司都会收到成千上百份的简历,因为面试官无法看到投递者这个人,所以其只能通过简历来识别这个人,那么读者就可以认为每一份简历就相当于是每个进程所专属的【PCB对象】
  • 所以面试官对于面试者的管理就是对简历的管理。让进程去某个队列里排队,不是让代码去排队,而是进程的PCB结构体对象去排队

        我在一开始的时候就讲到过,在内存中不仅仅是跑着一个进程,而是有可能会存在多个进程。那对于这多个进程要如何去起到关联呢?

  • 这一点其实我们在讲操作系统的时候也有讲到过,我们学习编程语言,像C/C++、Java可以帮助我们去很好地描述一个抽象的事物;我们学习数据结构与算法,可以帮助我们更好地去组织相同的对象数据
  • 那么在Linux内核中,最基本的组织进程的是用task_struct的方式,采用【双向链表】组织的

那有了上面的这个理论,操作系统在对于进程的管理就转换成了对于链表的增删查改 

三、查看进程 

 明白了操作系统如何去描述并组织进程,接下去我们就切身地来看一看进程长什么样吧

 下面呢是我们要进行测试的代码:

#include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <sys/types.h>
  5 int main()
  6 {
  7   // 死循环
  8   while(1)
  9   {
 10     pid_t id = getpid();
 11     //pid_t fid = getppid();
 12     //printf("I am a process! pid : %d, ppid : %d\n",id,fid);
 13     printf("I am a process! pid : %d\n",id);
        //程序停留一秒在输出                                                                     
 14     sleep(1);
 15   }
 16 
 17   return 0;
 18  }

💦 通过 ps 命令查看进程 

 ① 通过ps ajx命令查看进程

 查看当前我们正在运行的进程

 ② 此时我们来查看以下当前运行程序的进程

ps ajx | head -1 && ps ajx | grep mytest

 解析:

  1. ps ajx —— 查看当前系统中所有进程
  2. head -1 —— 获取第一行
  3. grep mytest —— 过滤只带【mytest】的进程

💬 那有同学可能会问:为什么在过滤进程的时候会有grep --color=auto mytest这个东西呢?

 当grep在进行过滤的时候自己也要变成一个进程,也可以看到他们使用grep命令的时候也带【mytest】关键字的,所以在过滤的时候把自己也过滤出来了。这也侧面证明了所有指令在运行的时候都是进程

  • 但如果我们不想看到这个也是有办法的,那就是在【grep】命令后面加个-v grep把其过滤掉即可
ps ajx | head -1 && ps ajx | grep mytest | grep -v grep

 💦 通过 ls / proc  命令查看进程 

 我们都清楚根目录下有很多的路径

 注意上面的proc目录,它是一个内存文件系统,里面放的是当前系统实时的进程信息。我们进入此目录看看:

  • 但是呢,上面这些呢是全部的进程,若我们只是想要查看某个进程的话就要根据其PID值去进行对应的查找。这个PID呢就是我们在上面在介绍task_struct这个Linux下的PCB结构体的时候所讲到的【标识符】这个东西,它是 描述本进程的唯一标示符,用来区别其他进程

  • 但是这么看不够清晰,我们以列表的形式来进行查看。这里我们主要关注两个:一个是cwd目录,另一个则是exe

首先我们来看到的是这个【exe】,很明显它是一个可执行文件,那就是我们在当前目录下的mytest这个可执行文件
接下去的话就是这个【cwd】了,其意思为current work directory当前进程的工作目录
 


接下来,我们来详细说一这个  cwd

看下的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
   
int main()
 {
    printf("我的PID:%d\n",getpid()); 
    FILE* fp = fopen("log.txt","w");                                                                                                                                
  
    if(fp==NULL)
    {
      return 1;
    }
    fclose(fp);
  
    printf("新建文件完成\n");
    sleep(50);
 
 return 0;
 }

 在当前的【proc.c】程序中,创建一个log.txt 的文件,创建好后,大家觉得这个文件会出现在哪里呢? 我们运行以下看看

我们发现在【proc.c】程序中创建的 log.txt文件出现在当前目录下,这是为什么呢?


我们来根据程序中的进程标识符来检查一个这个进程

        此时我们发现进程中的存有cwd---当前工作目录,所以导致在此程序中创建的任何文件,在没有指定放在哪里的时候,常见的文件会默认放在进程指定的cwd----当前工作目录下

 💦通过系统调用获取进程标示符

 上面我们有讲到了这个PID进程标示符,是通过ps这个命令来查看的,那我们能否直接获取这个PID

  • 在上面我们使用ps ajx查看到了当前进程所对应的 PID,但是呢这相当于是遍历操作,如果我没有加grep mytest的话出来的进程数就会很多了
  • 那现在我们所要做到的就是对一个单独的进程去获取其 PID,此时我们能想到的就是通过库函数来实现。在之前的文章中我们又说到过对于操作系统而言它是不会相信任何人的,所以会提供给用户一些系统调用(库函数),那我们只需要通过这个系统调用即可获取到当前进程的 PID 值

  • 那首先呢,我们先要去查询一下这个getpid()怎么使用,那还是使用到我们的老朋友man
man 2 getpid
  • 进去之后看到,有两个库函数,那如果要使用这两个库函数的话就需要引入对应的头文件

下面我给出一段命令,它可以实时监控当前系统的进程

while :;do ps ajx | head -1 && ps ajx | grep mytest | grep -v grep; echo "------------------------------------------------------------"; sleep 1; done; 
  • 然后就让我们来观察一下其是否真的可以获取到当前进程的PID,首先运行上面的这段指令,我们看到了当前系统中并不存在有关mytest的进程,但是呢在我们把mytest这个可执行程序运行起来的时候,右侧就突然就多出了一条进程的相关信息
  •  后一核对相关的PID值就发现确实是当前运行起来的这个进程

  • 但是呢当我在将当前这个进程给结束之后再去把它起起来的时候,就发现当前这个进程的PID值发生了变化

💬 其实的话,这个现象是很正常的,每次重新启动进程其 PID 值是会出现不同的情况

  • 举个很简单的例子来说吧,小王在高考结束完后上了一所不是很理想的大学🏫,在开学前两天时学习为其分配了对应的学号。但是呢小王却并不满意自己所待的这个学校,所以就退了学继续参加高考,在又一次的高考结束后他还是被原来的这所学校给录取。但是呢我们可以知道,即使你进了一个学校两次,但是学号却不一定是一样的
  •  这也就是为什么一个进程在启动两次后会出现不同PID值的原因

 刚才我们在通过【man】手册查看getpid()这个函数的时候,还看到了getppid()这个函数,它是获取当前进程的父进程的 PID

  • 这个PPID呢就在PID的左边

  • 下面是改进的测试代码
printf("I am a process, my id is: %d, parent is: %d\n", getpid(), getppid());
  • 马上来看一下是否真的可以获取到

  • 接下去我们再来观察一下现象:通过3次结束子进程,我们观察到了子进程确实每次都会发生变化,但是呢对于父进程而言却不会发生任何的变化,这是为什么呢?

  • 我们可以先去查看一下这个父进程到底是什么鬼…(((m -__-)m
ps ajx | head -1 && ps ajx | grep 18866
  • 然后我们就可以发现这个父进程原来是bash,它可以执行我们所输入的命令

原因解析:
① 每次在登录XShell的时候,系统会为我们单独再创建一个Bash进程,即命令行解释的进程,帮我们在显示器中打印出对话框终端

[XAS@iZf8z3lh8un7rc5rk1ney3Z lesson13]$  -----  【父进程----ppid】

② 我们在命令行中输入的所有指令都是Bash进程的子进程Bash进程只负责命令行的解释,具体执行出问题的时候只会影响它的子进程

ls /proc/18866	-- 子进程【PID】

上面这样解释可能还是比较抽象,一样来举个例子

  • 还记得,我们在讲解shell运行原理的时候曾经说到过王婆是一位资本家,她为了不损坏自己的名声呢,在别人找她说媒的时候会派遣一些实习生去,即使实习生出了问题她的名誉也不会受到影响

 这就可以对照到父进程与多个子进程,可以有多个子进程在这个父进程上面运行,即使某一个子进程突然出问题终止了,还有其他子进程在运行,此时父进程也是有保障的,所以子进程每次都会发生变化,但是父进程永远都不会变化

四、共勉 

 以下就是我对【Linux系统编程】进程概念的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对【Linux系统编程】创建进程理解,请持续关注我哦!!!  

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

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

相关文章

怎么判断香港服务器的性能好不好?

随着互联网的不断发展&#xff0c;越来越多的人开始使用香港服务器来搭建自己的网站或者应用。但是&#xff0c;对于初次使用香港服务器的用户来说&#xff0c;往往会遇到一个问题&#xff1a;怎么判断香港服务器的性能好不好? 首先我们需要了解香港服务器的性能主要取决于哪些…

今日 LeetCode热题100--c++代码附思路

目录 1.最长连续序列 题目描述​编辑 通过代码 2.移动零 题目描述 通过代码 3.盛最多水的容器 题目描述 通过代码 1.最长连续序列 题目描述 通过代码 class Solution { public:int longestConsecutive(vector<int>& nums) {//排序&#xff0c;相同字母跳过…

TiDB 7.x 源码编译之 TiDB Server 篇,及新特性详解

本文将介绍如何编译 TiDB Server 源码。以及阐释 TiDB Server 7.x 的部分新特性。 TiDB v7.5.0 LTS 计划于 2023 年 11 月正式 Release&#xff0c;目前代码虽未冻结&#xff0c;但已经可以看到 Alpha 版本的 Code 了&#xff0c;本文代码将以 v7.5.0-alpha 为基准。 TiDB Se…

16、定时器

定时器介绍 定时器介绍&#xff1a;51单片机的定时器属于单片机的内部资源&#xff0c;其电路的连接和运转均在单片机内部完成 定时器的作用&#xff1a; 1、用于计时系统&#xff0c;可实现软件计时&#xff0c;或者使程序每隔一固定时间完成一项操作 2、替代长时间的Delay,提…

后端整合Swagger+Knife4j接口文档

后端整合SwaggerKnife4j接口文档 接口文档介绍 什么是接口文档&#xff1a;写接口信息的文档&#xff0c;条接口包括&#xff1a; 请求参数响应参数 错误码 接口地址接口名称请求类型请求格式备注 为什么需要接口文档 who用&#xff1f;后端提供&#xff0c;前后端都需要使用…

入侵redis之准备---VMware安装部署kail镜像服务器【详细包含云盘镜像】

入侵redis之准备—VMware安装部署kail镜像服务器【详细包含云盘镜像】 kail是一个很好玩的操作系统&#xff0c;不多说了哈 下载kail镜像 kail官网:https://www.kali.org/get-kali/#kali-platforms 百度云盘下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1PRjo…

安卓开发学习---kotlin版---笔记(一)

Hello word 前言&#xff1a;上次学习安卓&#xff0c;学了Java开发&#xff0c;简单的搭了几个安卓界面。这次要学习Kotlin语言&#xff0c;然后开发安卓&#xff0c;趁着还年轻&#xff0c;学点新东西&#xff0c;坚持~ 未来的你会感谢现在努力的你~ 主要学习资料&#xff1a…

vscode注释插件「koroFileHeader」

前言 在vscode上进行前端开发&#xff0c;有几个流行的注释插件&#xff1a; Better CommentsTodo TreekoroFileHeaderDocument ThisAuto Comment Blocks 在上面的插件中我选择 koroFileHeader 做推荐&#xff0c;原因一是使用人数比较多&#xff08;最多的是 Better Commen…

外贸人如何优化资金管理链路,让「主子账户」助您事半功倍

如果一家外贸企业在大陆、香港同时拥有多个主体&#xff0c;该如何提升关联公司的账户管理效率&#xff1f; 使用iPayLinks主子账户功能&#xff0c;助力外贸企业轻松实现多账户资金的统一管理和掌控&#xff01; 多账户资金统一管理 1个主账户 可添加多达50个子账户 无需切…

人工智能_机器学习053_支持向量机SVM目标函数推导_SVM条件_公式推导过程---人工智能工作笔记0093

然后我们再来看一下支持向量机SVM的公式推导情况 来看一下支持向量机是如何把现实问题转换成数学问题的. 首先我们来看这里的方程比如说,中间的黑线我们叫做l2 那么上边界线我们叫l1 下边界线叫做l3 如果我们假设l2的方程是上面这个方程WT.x+b = 0 那么这里 我们只要确定w和…

亚马逊低价产品广告怎么打?亚马逊造成成本高的原因——站斧浏览器

亚马逊低价产品广告怎么打&#xff1f; 设置合适的出价&#xff1a;在低价自动广告中&#xff0c;设置适当的出价是关键。过高的出价可能导致广告成本过高&#xff0c;而过低的出价可能使广告曝光度不足。可以根据产品的竞争情况和预算来调整出价&#xff0c;找到一个平衡点。…

冲刺高端,OPPO不太OK?

所有人都知道OPPO有一个高端梦&#xff0c;而折叠屏似乎就是其弯道超车实现高端化的关键所在。然而如今看来&#xff0c;折叠屏手机在市场的表现似乎并没有成为主流&#xff0c;这或许也意味着OPPO距离自己的高端梦似乎还有些距离。 更高端&#xff0c;往往意味着更多的利润和价…

ATFX汇市:英、日、欧央行行长同日发声,均强调2%通胀目标尚未达成

ATFX动态&#xff1a;11月27日&#xff0c;英国央行行长贝利表示&#xff0c;“我们必须将&#xff08;通胀&#xff09;降到2%&#xff0c;这就是为什么我最近一直在给有关我们正在讨论降息或者我们将在可预见的未来降息的假设泼冷水&#xff0c;因为现在谈这个问题还太早”。…

Elsevier的latex模板

1.关于Elsevier的letex模板&#xff08; version 2.3 2021-05-11)一开始直接编辑出现The key ‘stm/author/&#xff1c;options&#xff1e;‘ is unknown and 的问 LaTeX Error: The key stm/author/<options> is unknown and is being ignored. 关于Elsevier的letex…

现货白银交易系统失灵了咋办?

在现货白银交易中&#xff0c;投资者常常会吐槽说&#xff0c;这个交易系统失灵了&#xff0c;并且他们还会感到很紧张&#xff0c;因为系统的失灵&#xff0c;可能意味着投资者策略不能发挥作用&#xff0c;进而出现亏损。其实&#xff0c;在网络时代&#xff0c;尤其是自动交…

IDEA不支持Java8了怎么办?

IDEA不支持Java8了怎么办&#xff1f; 01 异常发生场景 当我准备创建一个springboot项目时&#xff0c;发现Java8没了 02 问题的产生及其原因 查阅了官方文档之后&#xff0c;确认了是Spring Boot 不再支持 Java 8&#xff0c;不是我的问题&#xff0c;这一天终于还是来了 0…

filebeat(远程收集日志工具)

&#xff08;一&#xff09;filebeat 1、filebeat和logstash相同 &#xff08;1&#xff09;filebeat是一个轻量级的日志收集工具&#xff0c;所使用的系统资源比logstash部署和启动时使用的资源要小的多 &#xff08;2&#xff09;filebeat可以运行在非Java环境、可以代理l…

初始化的内容写到析构函数中。。。。。。。

大概是&#xff0c;把应该在构造函数中初始化的堆栈窗体代码写到了析构函数中。。。。 不是因为没掌握构造/析构&#xff0c;而是。。。。 检查了四十多分钟没检查出来。。 被自己蠢哭。 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) { }…

数学老师怎么和家长沟通

作为一名数学老师&#xff0c;与家长建立良好的沟通关系是非常重要的。以下是我个人认为可以帮助与家长有效沟通的建议&#xff1a; 建立良好的第一印象 第一次与家长接触时&#xff0c;要尽可能展现出你的专业素养和热情。在交流中&#xff0c;要表达出你对孩子的关心和重视&…

全面介绍SSO(单点登录)

全面介绍SSO&#xff08;单点登录&#xff09; SSO英文全称Single SignOn&#xff0c;单点登录。SSO是在多个应用系统中&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比…