linux进程管理,一个进程的一生(喂饭级教学)

这篇文章谈谈linux中的进程管理

一周爆肝,创作不易,望支持!

希望对大家有所帮助!记得收藏

要理解进程管理,重要的是周边问题,一定要知其然,知其所以然。看下方目录就知道都是干货!

目录

1.什么是进程管理?

2.为什么要有进程管理?

3.如何对进程进行管理?

(1)描述进程

(2)组织进程

4.查看系统中的进程

(1)命令查看

(2)文件查看

5.创建进程的两种方式

(1)./运行一个程序

(2)通过代码创建

6.父子进程与fork()

(1)父子关系

(2)系统调用fork()

(3)fork()原理

1.fork()干了什么事?

2.为什么fork()会有两个返回值?

3.为什么fork()给父进程返回子进程pid,给子进程返回0?

4.fork()之后,父子进程谁先运行?

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

6.重新理解fork()

7.进程状态

(1)一般操作系统的进程状态

1.运行状态

2.阻塞状态

3.阻塞挂起和swap分区

(2)linux的进程状态

linux进程的休眠状态

linux僵尸进程和孤儿进程

8.进程状态切换

CUP运行队列中的进程如何调度?

9.进程的性质

1.进程的竞争性

2.进程的独立性

3.进程的并行、并发

10.进程的优先级和时间片

11.进程间切换

12.linux内核2.61CPU运行队列窥视(综合理解!)


1.什么是进程管理?

OS内核中有内存管理,进程管理,文件管理,驱动管理,OS将这四样管理起来才基本可以实现硬件和数据的自由调控,才可成为一个优质内核。

2.为什么要有进程管理?

要知道为什么要有进程管理,首先要知道进程是什么东西,这里给出进程的定义

进程的定义程序的一个执行实例,加载到内存中的程序,即正在执行的程序。进程是操作系统执行任务的基本单元,也是分配资源、处理数据和被调度的基本单元。更加通俗的理解:操作系统要做事情,进程就是一件又一件的"事情"

3.如何对进程进行管理?

在哲学的范畴,管理的本质对数据的管理,而非对具体对象的管理管理的策略是先描述,再组织。即先将被管理对象进行建模描述为抽象类型,再想好如何将每个被管理对象组织起来。

操作系统对进程的管理也是如此:

描述进程、组织进程

(1)描述进程

在操作系统中,经常将描述进程的类称为PCB(process control block)。进程的属性有很多:比如pid,ppid(父进程pid),stat(进程状态),进程优先级等等。后续慢慢学习······

struct PCB
{int pid;int ppid;int stat;......
};

(2)组织进程

进程的组织就是用高效的数据结构将进程对象组织起来,操作系统一般用双向链表将进程的PCB对象组织起来

4.查看系统中的进程

(1)命令查看

ps ajx //查看当前所有进程
ps ajx | head -1 && ps ajx | grep mybin//查看指定进程mybin

(2)文件查看

根目录下的proc目录中有当前存在的所有进程,因此这个目录是动态的。

这个目录里的各个数字目录,就是以各个进程的pid命名的。目录里面放的就是进程PCB对象的各种属性。 

5.创建进程的两种方式

(1)./运行一个程序

本质将磁盘上的可执行程序代码和数据拷贝到内存当中,为这个进程创建PCB对象,将PCB对象链入内存中管理PCB对象的双链表中(重点)

(2)通过代码创建

使用fork()函数创建当前进程的子进程。

6.父子进程与fork()

(1)父子关系

进程是有父子关系的,在一个进程中创建出新的进程,这个新的进程就被叫做那个进程的子进程。那个进程叫做新的进程父进程

(2)系统调用fork()

fork()是一个进程通过代码创建子进程的时候,所调用的系统接口。通过fork()函数,在fork()下一行处会创建一个子进程,这个子进程和父进程共同执行接下来的代码

如图:

./mybin运行之后 

体现出了fork()之后, 子进程和父进程两个执行流分别执行接下来的代码。

fork()函数

头文件#include<unistd.h>

返回值:父进程返回子进程pid,子进程返回0。

(3)fork()原理

1.fork()干了什么事?

现象:fork()是系统接口,fork()之后会为父进程创建子进程,父子进程两个执行流共同执行fork()之后的代码。

本质:进程的创建,本质是将可执行程序代码和数据加载到内存中,创建PCB对象,再将PCB对象链接到管理PCB对象的双向链表中。父进程中使用fork()创建进程本质是以父进程PCB为模板创建子进程PCB,由于子进程没有从磁盘中加载代码和数据,子进程的PCB只能指向父进程的代码和数据,因此父子进程共享代码子进程可以看到父进程的全部代码,由于进程的独立性,数据会以写时拷贝的方式给到子进程。

2.为什么fork()会有两个返回值?

fork()函数在return x 之前,子进程就被创建出来了,所以不要把fork()看成一个整体,return之后父子进程两个执行流共同执行接下来的代码,return也被父子进程以不同的值返回两次

3.为什么fork()给父进程返回子进程pid,给子进程返回0?

给父进程返回子进程的pid,是为了让父进程较好的控制管理子进程,所以返回子进程的pid让父进程进行控制。子进程只需要确认自己创建成功与否,所以返回0。

4.fork()之后,父子进程谁先运行?

fork()后,父子进程都会进入CPU的执行队列中被调度,需要依赖进程PCB的调度优先级和调度器算法。

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

父子进程共享代码,但是要保证进程的独立性数据不能共享,所以数据会以写时拷贝的方式拷贝给子进程,return两个值本质是写两次数据,子进程的数据就要写时拷贝。因此父子进程都有自己存储返回值的变量。

6.重新理解fork()

7.进程状态

(1)一般操作系统的进程状态

进程的状态指的是一个进程处在内存中某个PCB队列中所体现出来的状态。进程的状态是为了更好的让操作系统得知每个进程的实时情况所设定的。进程可以在很多PCB队列中进行排队。进程状态是PCB中的一个属性,是一个int类型的值,来表示这个进程目前的状态

1.运行状态

我们把进程的PCB在CPU的运行队列中排队的状态认定为运行状态。在CPU运行队列的进程准备被调度(取决于调度器算法)。

2.阻塞状态

当我们的进程在CPU的运行队列中被调度的时候,这个进程开始让CPU来执行它的可执行程序,这个可执行程序势必或多或少会访问到操作系统中的软硬件资源,如果此时要访问的软硬件资源还没有到位,那么这个进程的PCB就会从CPU的运行队列上剥离,去到软硬件资源的等待队列中排队,此时这个进程的状态被设置为阻塞状态

3.阻塞挂起和swap分区

硬件阻塞

当我们的进程处于阻塞状态,进程的PCB在对应软硬件资源的等待队列中排队,此时这个进程的代码数据和PCB都在内存中占用着资源,但是这个进程暂时不需要被调度,如果此时操作系统的内存资源严重不足,就会把这个进程的代码和数据交换到磁盘中的swap分区中,为内存腾出空间。此时进程就处于阻塞挂起状态。当软硬件资源就绪时,操作系统再把这部分代码和数据唤回内存中,此时进程再从软硬件资源的等待队列中剥离到CPU的运行队列中排队。

软件阻塞

用linux调试代码工具gdb来解释一下就是,gdb在调试程序的过程中要根据断点来追踪、暂停进程,要想调试一个程序的代码,gdb和这个程序必须都加载到内存当中成为进程,CPU执行代码遇到断点进程就被阻塞了,需要等待gdb这个进程的继续操作,此时这个进程就需要等待软件资源gdb的响应,而gdb又要等待诸如键盘的响应,所以进程的PCB到gdb这个进程的PCB里的等待队列里排队,gdb这个进程PCB又到键盘的等待队列里排队。当键盘响应gdb,gdb的PCB又到CPU的运行队列里排队,待调试代码的进程也到CPU的运行队列里排队。

(2)linux的进程状态

linux进程状态主要有一下几种:

static const char * const task_state_array[] =
{"R (running)", /* 0 */  //运行状态"S (sleeping)", /* 1 */   //休眠状态"D (disk sleep)", /* 2 */   //深度休眠状态"T (stopped)", /* 4 */    //暂停状态"t (tracing stop)", /* 8 */   //追踪暂停状态"X (dead)", /* 16 */    //死亡状态"Z (zombie)", /* 32 */   //僵尸状态
};
linux进程的休眠状态

本质就是阻塞状态(可以随时被终止)。这里还有一个深度休眠状态disk sleep(磁盘休眠)当一个进程在向磁盘上写入数据的时候,这个进程需要等待磁盘写入完毕,并把写入结果返回给进程PCB,由于这个过程中进程不可被终止(防止数据丢失)此时这个进程的状态就是深度休眠状态。

linux僵尸进程和孤儿进程

当一个进程的可执行程序已经在CPU上跑完了,这个进程的生命周期就结束了,此时操作系统会先将这个进程的代码和数据进行释放,暂时不会释放这个进程的PCB。为什么?由于进程退出时的退出信息会保存在进程的PCB中,而操作性系统或者父进程要得知进程的退出原因(任务完成情况),所以要在父进程或者操作系统读取到退出信息之后,进程才能完全销毁,将进程PCB也释放。linux规定:进程在退出后,进程的PCB还没有被父进程或者操作系统读取到,进程还没有完全退出的进程状态僵尸状态。如果进程一直处于僵尸状态,会导致内存泄露的问题。

上面所说,进程在退出时,PCB是由父进程来回收的。那么,如果进程退出前,父进程就已经退出了,那这个进程的PCB就没有相应的进程来回收了,此时进程的状态成为孤儿状态

8.进程状态切换

切换本质 : 进程的状态切换,本质就是进程的PCB不同队列中做不停的跳转

CUP运行队列中的进程如何调度?

9.进程的性质

1.进程的竞争性

系统进程众多,而CPU资源只有少数,甚至一个,所以进程之间是具有竞争属性的。为了高效完成任务,合理竞争相关资源,便有了进程优先级和时间片已经调度器算法。

2.进程的独立性

各个进程运行期间互不干扰,各自独立。

3.进程的并行、并发

并行:多个进程分别在多个CPU上同时运行。

并发:多个进程在单个CPU上采取进程切换的方式,在一段时间内让多个进程都得以推进。

不要用人的感知来感受CPU的处理速度,例如每个进程的时间片是0.0001秒,CPU就执行每个进程0.0001秒,在一秒的时间内,上百个进程,每个都被CPU推进了100次!CPU的运行速度之快,决定了进程并发的可行性。

10.进程的优先级和时间片

linux进程的优先级范围是60-99,默认优先级为80。优先级由默认优先级和nice值共同决定,例如:创建一个进程,这个进程的默认优先级为80,同时把nice设置为10,进程的最终优先级为80+nice=90。

时间片决定了一个进程每次使用CPU资源的最大时间限度。当一个进程使用CPU资源的时间超过时间片,进程就会自动剥离,等待下次被调度。

11.进程间切换

进程间切换指的是进程PCB在CPU运行队列中,上、下的反复过程。下去的进程要打包带走自己的寄存器数据,上来的进程要将自己的寄存器数据拷贝给寄存器硬件

12.linux内核2.61CPU运行队列窥视(综合理解!)

现在执行一个可执行程序mybin。

./mybin

 一个进程的一生开始了!

1.此时,操作系统在内存中创建这个可执行程序的PCB,并把磁盘上的代码和数据拷贝到内存中。

2.PCB放入CPU运行队列中的过期队列中等待被调度。需要等待活跃队列中的PCB全部剥离,PCB剥离需要同时带走自己的寄存器数据保存在自己的PCB中。

3.活跃队列中的PCB全部剥离,swap两队列的指针,开始按照优先级执行活跃队列(原过期队列)中的进程。每个进程让CPU执行,需要把PCB内的寄存器数据拷贝给寄存器。

4.该你执行了,CPU开始执行代码,代码中要访问软硬件资源但没有就绪,阻塞!PCB进入对应的等待队列。(剥离时带走自己的寄存器数据)

5.软硬件资源就绪,PCB被唤回CPU运行队列中的过期队列中等待被调度。

6.又轮到你了,将寄存器数据交给寄存器,继续从上次阻塞的地方开始执行。

7.时间片到了,剥离到过期队列中。

8.活跃队列中的PCB全部剥离,再swap两队列的指针。CPU开始执行过期队列中的进程。

9.又轮到你了,这次CPU在时间片结束时间内把代码执行完了,进程将要结束了。

10.父进程把你的代码和数据释放,将PCB内的退出数据读取完毕,把PCB也释放。进程Z状态。

本次分享就到这里,如果对大家有用的话,希望程序猿们可以三连支持一下,会继续分享知识,加油!

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

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

相关文章

【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建

为摒弃在接受keil邮件&#xff0c;研究了下gun编译&#xff0c;以STM32F407为例&#xff0c;简单记录 1. 软件包准备 Git 选择对应版本直接安装即可https://git-scm.com/download/winmakegcc ​ 1&#xff09;将上述软件包放置于C盘根目录 2&#xff09;添加环境变量 3&am…

【Git】idea提交项目到Gitee

文章目录 1. 创建Gitee仓库1. 新建仓库2. 添加描述3. 复制仓库地址 2. idea建立连接提交2.1 Create Git Repository2.2 选择要提交的根目录2.3 Commit2.4 Push2.5 提交成功 1. 创建Gitee仓库 1. 新建仓库 2. 添加描述 3. 复制仓库地址 点击右上角克隆/下载&#xff0c;复制HT…

pv操作题目笔记

对于 pv 操作分以下几步走 什么是pv操作 PV操作在进程同步中通常指的是信号量&#xff08;Semaphore&#xff09;操作。信号量是一种用于控制多个并发进程或线程之间的同步和互斥访问的同步工具。PV操作通常涉及两个基本操作&#xff1a;P操作&#xff08;wait操作&#xff0…

MD5生成和校验

MD5生成和校验 2021年8月19日席锦 任何类型的一个文件&#xff0c;它都只有一个MD5值&#xff0c;并且如果这个文件被修改过或者篡改过&#xff0c;它的MD5值也将改变。因此&#xff0c;我们会对比文件的MD5值&#xff0c;来校验文件是否是有被恶意篡改过。 什么是MD5&#xff…

微信小程序实现类似于 vue中ref管理调用子组件函数的方式

微信小程序中确实有类似于 vue 中 ref管理子组件的方式、 这里 我给子组件定义了一个 class 只要是 css选择器拿得到的 都没什么问题 但你要保证唯一性 建议前端开发还是慎重一点 就算是不能重复也尽量用class 因为id总还是有风险的 然后 我在子组件中顶一个了一个函数 start…

计网----数据包在传输中的变化过程,单播组播和广播,ARP协议,ARP代理,免费ARP,DNS协议,路由数据转发过程

计网----数据包在传输中的变化过程&#xff0c;单播组播和广播&#xff0c;ARP协议&#xff0c;ARP代理&#xff0c;免费ARP&#xff0c;DNS协议&#xff0c;路由数据转发过程 一.数据包在传输中的变化过程&#xff08;在同一个路由器下&#xff09; 1.传输数据时&#xff0c…

RPA的尽头是超自动化?

超自动化在经过数年的发酵期后&#xff0c;已从一个科技概念崛起为市值近千亿元的新赛道&#xff0c;包括各大互联网巨头、科技公司都纷纷围绕超自动化进行战略布局。 一方面&#xff0c;是行业巨头选择纷纷跻身超自动化新赛道&#xff0c;另一方面&#xff0c;RPA行业的领军企…

Proteus仿真--VB上位机程序控制DS1302时钟仿真(Proteus仿真+程序)

本文主要介绍基于51单片机的VB上位机程序控制DS1302时钟仿真设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 简介 硬件电路主要分为单片机主控模块、DS1302模块、LCD1602液晶显示模块以及串口模块 &#xff08;1&#xff09;单片机主控模块&#xff1a;单片机选…

Git最佳实践:git常用命令和原理

Git 是一个开源的分布式版本控制系统。 Git 工作区、暂存区和版本库 工作区&#xff1a;就是你在电脑里能看到的目录。暂存区&#xff1a;英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件&#xff08;.git/index&#xff09;中&#xff0c;所以我们把暂存区有时…

Leetcode—104.二叉树的最大深度【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—104.二叉树的最大深度 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root){…

热点不热!如何修复笔记本电脑未连接到移动热点的问题

当你远离常规Wi-Fi时,移动热点是让你的笔记本电脑上网的关键,但当它没有按计划运行时,你会怎么办?以下是Windows笔记本电脑无法连接到移动热点时的几种修复方法。 为什么我的笔记本电脑没有连接到我的热点 由于你的笔记本电脑正试图连接到另一个有限制和可能存在问题的设…

PHP yield

概念&#xff1a; Generator&#xff1a;带 yield的function yield&#xff1a;Generator或task的中断关键字&#xff0c;执行到yield时一次调度周期执行完即阻塞&#xff0c;并返回右侧表达式结果&#xff0c;等待下一次调度器运行next()或迭代遍历才会继续往下执行&#xff0…

2023-10-23 LeetCode每日一题(老人的数目)

2023-10-23每日一题 一、题目编号 2678. 老人的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的字符串 details 。details 中每个元素都是一位乘客的信息&#xff0c;信息用长度为 15 的字符串表示&#xff0c;表示方式如下&#xff1a; 前十…

rust学习——泛型 (Generics)

文章目录 泛型 Generics泛型详解结构体中使用泛型枚举中使用泛型方法中使用泛型为具体的泛型类型实现方法 const 泛型&#xff08;Rust 1.51 版本引入的重要特性&#xff09;const 泛型表达式 泛型的性能 泛型 Generics Go 语言在 2022 年&#xff0c;就要正式引入泛型&#xf…

mysql下载和安装,使用

先下载安装 官方下载 已下载备份软件 安装&#xff0c;一路下一步设置环境变量 4. 打开一个cmd&#xff0c;输入mysql -u root -p

Spark内核调度

目录 一、DAG &#xff08;1&#xff09;概念 &#xff08;2&#xff09;Job和Action关系 &#xff08;3&#xff09;DAG的宽窄依赖关系和阶段划分 二、Spark内存迭代计算 三、spark的并行度 &#xff08;1&#xff09;并行度设置 &#xff08;2&#xff09;集群中如何规划并…

Visual Studio Code官网下载、vscode下载很慢、vscode下载不了 解决方案

前言 开发界的小伙伴们对于Visual Studio Code开发环境来可以说非常熟悉了&#xff0c;但由于在Visual Studio Code官网的下载速度非常的慢&#xff0c;即便开了代理也是一样的很慢、甚至下载被中断&#xff0c;几乎不能下载。 解决方案 1、在Web浏览器上打开vscode官网&#…

RabbitMQ基础篇 笔记

RabbitMQ 余额支付 同步调用 一步一步的来&#xff0c;支付业务写完后&#xff0c;如果之后加需求&#xff0c;还需要增加代码&#xff0c;不符合开闭原则。 性能上也有问题&#xff0c;openfeign是同步调用&#xff0c;性能太差。 同步调用耦合太多。 同步的优势是可以立…

Android View拖拽startDragAndDrop,Kotlin

Android View拖拽startDragAndDrop&#xff0c;Kotlin import android.os.Bundle import android.util.Log import android.view.DragEvent import android.view.View import android.view.View.OnDragListener import android.view.View.OnLongClickListener import android.w…

C语言之排序

1.冒泡排序 冒泡排序就不多说了&#xff0c;只需要两层循环嵌套&#xff0c;两两比较确定相对正确的顺序即可。 2.插入排序 插入排序的思想就是每一次向后寻找一个再将其与前面有序的部分进行对比&#xff0c;寻找合适位置插入。 这里关键要避免让前移超出目前读取的数字&…