Linux_进程

目录

1、冯诺依曼体系

2、Linux下的进程概念 

3、PCB结构体

4、在Linux下查看进程

5、父子进程

6、终止进程 

7、操作系统的进程状态 

7.1 Linux下的进程状态

8、孤儿进程 

9、进程优先级 

9.1 PRI和NI 

结语 


前言:

        进程作为操作系统中最核心的知识点之一,也是最重要的一环,正因为有了进程的概念,我们在使用电脑时才可以同时打开多个软件,我们给电脑的每一个指令在操作系统的层面上几乎都可以看成是一个进程,在Linux下也如此,Linux下之所以可以处理多种指令也离不开进程的作用,本文着重介绍Linux下的进程概念。

1、冯诺依曼体系

         在Linux下,当执行一个可执行程序或者执行一条指令时,都是让cpu对其进行计算的,因为在冯诺依曼体系中,cpu担任计算机系统的大脑,运行的任何文件包括指令,之所以可以在屏幕上看到运行的结果,都是因为cpu对其进行了计算。

        冯诺依曼体系结构如下:

         在该体系中,所有需要让cpu进行计算的任何程序或者指令,都必须加载到内存中,才能让cpu进行计算,换句话说,cpu只和内存打交道。

        而以上最主要的一点是:在这些指令或者程序被加载到内存中时,就变成了所谓的进程,详细如下文

2、Linux下的进程概念 

         在Linux下可以执行多条指令,原因就是指令或可执行程序在被加载至内存中变成了进程,但事实上操作系统做了更多的事情,因为Linux下的指令非常之多,比如:ls pwd cd..等等,这些指令从名称就能够看出来没有什么特别相似的地方,因此管理起来非常不方便,若连管理都无法做到,更别提让cpu去调度这些杂乱无章的进程了。

        因此在指令被加载到内存中时,系统会创建一个描述该指令属性的结构体PCB,对每个指令亦是如此,这样一来就能够将指令的相同属性提取出来,然后通过管理结构体PCB间接管理这些杂乱无章的指令(比如用链表的形式管理PCB,能够更好的实现增删查改的功能),所以一个真正意义上的进程=描述该指令的PCB+该指令的具体实现内容。(用PCB来管理对应的指令,就好比学校里用学生的各项成绩来决定学生的评分,目的就是为了更好的管理庞大的群体

        详细结构图如下:

        以管理PCB结构体的数据结构间接来管理各种指令,也就是说cpu调度的是PCB结构体而非指令本身。 

3、PCB结构体

         PCB结构体是操作系统中对描述进程属性的统一集合的名称,在Linux下PCB的结构体名称是task_struct,他们的作用都是将指令的共有属性描述出来,目的就是方便管理指令,更好的让cpu调度进程。

        task_struct的具体内容如下:

1、标识符: 描述某一个进程,以区分其他进程,是进程的唯一。
2、状态: 运行状态、阻塞状态、挂起状态等等,Linux下表示状态的符号为:R、S、D、T、t、X、Z。
3、优先级: 优先级高的进程会先被cpu调度,低的相反。
4、程序计数器: 保存即将执行的下一条语句的地址。
5、内存指针: 为了能够找对PCB对应的指令或者程序。
6、上下文数据: 当一个进程被cpu切出去时,会保存该进程被切出去时的临时数据,以便该进程下一次进入cpu时无需从头开始计算。
7、I/O状态信息: 保存进程涉及到的各种I/O设备。
8、记账信息: 保存处理器的使用时间总和。

4、在Linux下查看进程

        在Linux下有两种常用的方法可以查看当前系统的进程,1:用指令ps axj,2:ls /proc。用指令ps axj的运行结果如下:

        从上图中可以得出一些信息,每个进程都有属于自己的进程pid,但是也会有一个父进程ppid,可以理解为每个进程都会有一个父进程,和二叉树的根结点与子结点概念相似,进程是其父进程的一个分支。


        proc是一个目录,里面存放了所有进程的pid:

        可以发现proc目录下的进程pid可以和上面图中的进程pid对应起来。并且可以在proc内根据进程pid找到对应的执行指令和详细信息,具体如下:


        特别注意:在Linux下,我们提出的每一条指令,都会被当作是一个进程,因为指令要被cpu进行计算,而要被cpu计算则必须是进程,所以系统会自动分配一个子进程帮助我们执行各种指令,解释图如下:

 

5、父子进程

        pid表示一个进程的pid号,这是该进程独有的编号,而该进程ppid表示其父进程的pid号,每个进程都有pid和ppid,并且可以通过系统调用接口清楚的看到一个进程的pid和ppid。 

        getpid()和getppid()的接口信息如下:

         测试结果如下:

        从该进程的父进程pid可以看到,父进程pid为21533和上面测试进程的父进程pid是一模一样的,因此当我们登录一个用户时,系统会为该用户分配一个专门的进程(bash),这个进程会分支出无数的子进程供用户执行指令,所以我们执行指令的父进程都是bash进程。

6、终止进程 

        终止进程的概念对应windows下的从任务管理器结束一个进程,其在Linux下的指令为kill -9 要终止的进程pid,测试如下:

7、操作系统的进程状态 

         在操作系统的层面上,进程分为三种状态,即运行状态、阻塞状态、挂起状态。这里涉及到等待队列的概念,等待队列即一个进程的PCB结构体在等待cpu的调度或者外部资源的输入,这时候PCB会被放入对应的等待队列中。比如PCB结构体准备让cpu调度,则PCB结构体处于cpu调度的等待队列中

1、运行状态:即该进程被加载至内存中准备被cpu进行调度,称之为运行状态

2、阻塞状态:即一个进程被cpu调度时,该进程需要外部的输入资源,比如cin,scanf等输入键盘资源的情况时,该进程会从cpu中抽离出来等待外部资源输入后再进入cpu,把这个等待的过程称之为阻塞状态

3、挂起状态:即在阻塞状态的条件下,当下系统资源严重不足时,即使该进程在等待外部资源的输入时,也会将该进程的代码部分抽离等待行列,并放入磁盘中,只留下PCB结构体在等待队列中。

7.1 Linux下的进程状态

         Linux下的进程状态分布如下:

R (running)运行状态
S (sleeping)睡眠状态
D (disk sleep)深度睡眠状态
T (stopped)停止状态
t (tracing stop)跟踪停止状态
X (dead)结束状态
Z (zombie)僵尸状态

        R状态与S状态的测试如下(还是用上面的循环程序举例):

        R表示运行,S表示睡眠(对应阻塞)。+号表示在前台运行,即此时的命令框不能输入任何指令。 该循环程序的状态是S的原因在于,cpu每次读取进程会有一个时间片的概念,即一个进程在cpu中待的时间不能够超过10ms,超过了就会把该进程从cpu拿下来,否则cpu遇到死循环的程序则不能够计算其他的进程了(事实上我们运行了一个死循环程序,还可以输入其他的指令),所以cpu会将该死循环的程序拿下来去计算其他的进程,那么该进程就会被处于一个睡眠状态,即S状态,他在等待某种特定的资源后重新被唤醒并进入运行状态。


        当进程在写入数据时比如写进磁盘中(前提是处于高度IO的状态,可以理解为是S状态的深度版本),属于D状态(深度睡眠状态),D状态表示该进程会等待至I/O结束后才表示该进程结束,这个过程中该进程不能被操作系统强行中断。 


        t状态指的是当用gdb进行调试某个可执行程序时,对其中代码设置断点,这时候该进程就处于t状态。

        而用指令kill -19 进程pid,可以使该进程的状态设置为T。


        最后X状态和Z状态是对应的,即当一个进程结束了则该进程的状态为X,但是这个过程极快,无法观察捕捉到。

        若当一个进程已经结束了,但是该进程的父进程没有回收他的PCB资源(即父进程还在运行),则该进程就会处于X状态的前一个状态Z(僵尸状态), 表示该进程的代码和数据可能已经释放了,但是该进程对应的PCB结构体依然存在。

        测试僵尸状态下的现象:

  1 #include<stdio.h>2 #include<unistd.h>3 4 int main()5 {6         pid_t in = fork();//fork创建一个子进程7         if(in==0)8         {9          while(1)10          {11             printf("这是一个子进程:PID: %d PPID:%d\n    ",getpid(),getppid());12 13             sleep(5);                                14             return 1;//结束子进程15          }16         }17         else18         {19          while(1)20         {21             printf("这是一个父进程:PID: %d PPID:%d\n    ",getpid(),getppid());22 23             sleep(1);24 25         }26         }27     return 0;28 }

        测试结果:

        若进程处于僵尸状态,那么最终导致的危害就是内存泄漏,因为该进程虽然代码数据资源被释放了,但是在系统中,该进程的PCB结构体一直没有被父进程回收,而PCB结构体被创建出来也是需要占用内存资源的。 

8、孤儿进程 

        上述的僵尸进程指的是父进程不退出,而子进程先退出了,导致僵尸进程,而孤儿进程刚好与其相反,孤儿进程表示子进程还没退出,而父进程已经退出了,这时候父进程就会被其父进程(bash)回收,但是该进程的子进程还在运行,这时候该子进程就变成了孤儿进程。

        孤儿进程测试代码:

  1 #include <stdio.h>2 #include <unistd.h>3 #include <stdlib.h>4 int main()5 {6  pid_t id = fork();7  if(id < 0){8  perror("fork");9  return 1;10  }11  else if(id == 0){//child12  printf("I am child, pid : %d\n", getpid());13  sleep(10);14  }else{//parent15  printf("I am parent, pid: %d\n", getpid());16  sleep(3);                                           17  exit(0);//父进程先退出18  }19  return 0;20 }

         测试结果:

        子进程的ppid从6422变成了1,因为该子进程的父进程已经结束了,所以该子进程变成了孤儿进程,但是必须得有人来“领养”这个孤儿进程,否则该孤儿进程结束后会变成僵尸进程,就会一直导致内存泄漏,于是该孤儿进程就被分配给了操作系统,操作系统的pid即为1。

        注意此时的子进程的状态没有+号,表示他现在是一个后台进行的进程,前台无法使用ctrl + c结束该进程,只能使用kill -9指令将其结束。

9、进程优先级 

         首先cpu一次只能计算一个进程,只是cpu的计算速度非常快,以至于我们在使用操作系统的时候感觉像是多个进程同时在被计算,实际上只是cpu以极快的速度来回不断的计算内存中的进程,上文提到进程在cpu中待的时间不能超过10ms,就是为了可以让cpu处理其他进程,因为cpu一次只能计算一个进程。

        所以cpu对于进程来说是稀缺资源,当然cpu已经尽力保证每个进程都可以被调度到,但还是可以通过调整进程的优先级提高某个或降低某个进程被调度的先后顺序。

        优先级的标识符如下:

        默认可执行程序的PRI是80,NI是0。 

9.1 PRI和NI 

        PRI是表示进程的优先级,那么NI就是调整该优先级的一个手段,他们的关系为:PRI = PRI + NI。 比如将一个进程的优先级调高,那么需要把NI的值设为负数,比如NI = -10,那么PRI = 80+(-10)=70,则调整后的PRI的优先级比原来提高了10个等级。(注意:NI的范围是[-20,19]

        调整NI的指令操作如下,首先用指令top打开进程界面,然后按“r”,要求输入需要更改优先级的进程pid:


        输入进程后,输入NI的值,注意NI的范围:

        这里我们输入10,表示降低8820进程的优先级,则8820的进程PRI应该变成了90,最后通过ps -al查看进程优先级,如下:

结语 

         以上就是关于Linux下进程的讲解,进程作为操作系统中最重要的一环,他实现了操作系统可以高效率处理多个不同指令的功能,其功劳离不开冯诺依曼体系,因为该体系让计算机性价比达到最高,当然在此体系上,进程的本质是因为指令被对应的PCB结构体所采用数据结构的方式进行管理,对指令本体的执行变成了对数据结构的增删查改,因此大大提高了效率。

        最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!! 

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

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

相关文章

应急局rfid资产管理系统建设方案

应急局RFID资产管理系统的建设方案涉及以下几个方面&#xff1a; 1.需求分析&#xff1a;通过与应急局相关部门沟通&#xff0c;了解其对资产管理系统的需求&#xff0c;包括对资产的实时监控、定位追踪、盘点和管理等功能的要求。 2.系统设计&#xff1a;根据需求分析&#xf…

Linux下:gcc/g++调试工具gdb

gdb 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 gdb mybin debug和release debug debug模式下生成的可执行程序会添加调试信息&#xff0c;所以生成的可执行程序会较大 在使用gcc/g进行编译的时…

基于SpringBoot + Vue实现的学生心理咨询评估管理系统设计与实现+毕业论文+开题报告+答辩PPT

介绍 系统有管理员和用户。 管理员可以管理个人中心&#xff0c;用户管理&#xff0c;试题管理&#xff0c;试卷管理&#xff0c;考试管理等。用户参加考试。 学生心理咨询评估系统的登录流程&#xff0c;针对的角色就是操作员的操作角色。在登录界面需要的必填信息就是账号信…

Vue2之组件通信(爆肝)

大家有什么想看的可以在评论区留言&#xff0c;我尽量满足&#xff0c;感谢大家&#xff01; 组件通信是vue中一个非常重要的内容&#xff0c;我们需要掌握好组件通信&#xff0c;那么让我为大家介绍几种组件通信的方式吧&#xff01; 一、props 这是父传子的方式&#xff0…

Docker - 简介

原文地址&#xff0c;使用效果更佳&#xff01; Docker - 简介 | CoderMast编程桅杆https://www.codermast.com/dev-tools/docker/docker-introduce.html Docker是什么&#xff1f; Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 D…

vulfocus靶场thinkphp命令执行cve-2018-1002015

thinkPHP 5.0.x版本和5.1.x版本中存在远程代码执行漏洞&#xff0c;该漏洞源于ThinkPHP在获取控制器名时未对用户提交的参数进行严格的过滤。远程攻击者可通过输入‘&#xff3c;’字符的方式调用任意方法利用该漏洞执行代码 开启靶场&#xff1a; 使用工具&#xff1a; think…

适配器模式【结构型模式C++】

1.概述 适配器模式是一种结构型设计模式&#xff0c; 又称为变压器模式、包装模式&#xff08;Wrapper&#xff09; 将一个类的接口变换成客户端所期待的另一种接口&#xff0c;从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 2.结构 Target&#xff1a;适配…

python3如何提取汉字

采用正则表达式的方法对字符串进行处理。 str1 "&#xff5b;我%$是&#xff0c;《速$.度\发》中 /国、人"&#xff08;1&#xff09;提取汉字 汉字的范围为”\u4e00-\u9fa5“&#xff0c;这个是用Unicode表示的。 import re res1 .join(re.findall([\u4e00-\u9fa…

排序 “叁” 之交换排序

目录 1. 基本思想 2.冒泡排序 2.1 基本思想 2.2 代码示例 2.3 冒泡排序的特性总结 3.快速排序 3.1 基本思想 &#x1f335;hoare版本 &#x1f335;挖坑法 ​编辑 &#x1f335;前后指针版本 ​编辑 3.2 快速排序优化 &#x1f33b;三数取中法选key 3.4 快速排序…

命理八字之电子木鱼的代码实现

#uniapp# #电子木鱼# 不讲废话&#xff0c;上截图 目录结构如下图 功能描述&#xff1a; 点击一下&#xff0c;敲一下&#xff0c;伴随敲击声&#xff0c;可自动点击。自动点击需看视频广告&#xff0c;或者升级VIP会员。 疑点解答&#xff1a; 即animation动画的时候&…

git 基础配置

一、下载git sudo apt install git -y二、用户信息配置 $ git config --global user.name "John Doe" $ git config --global user.email johndoeexample.com检查配置信息 git config --list三、ssh密钥生成 1、进入~/.ssh mkdir ~/.ssh cd ~/.ssh2、生成密钥 …

计算机网络基础1--基础概念

1. IP地址 1.1 IPv4地址 分为网络号和主机号 地址块的第一个地址和最后一个地址通常不使用。 广播地址为主机号全取1的情况。 2. 常用报文格式 2.0 ethernet协议 2.1 arp协议 2.2 ip协议 2.3 tcp协议 2.4 udp协议 2.5 icmp协议