✨前言:本篇文章会对Linux中进程的基本概念进行讲解,以及对进程状态和进程优先级的概念进行讲解和实操演示
Linux进程
🏞️1.冯诺依曼体系结构
对于我们生活中常见的计算机,如笔记本. 还有我们不常见的计算机如服务器,大部分都遵守冯诺依曼体系结构.
截止目前:我们所认识的计算机,都是由一个个的硬件组成包括:
- 输入设备:键盘、话筒、摄像头、磁盘、网卡、鼠标、扫描仪等
- 中央处理器(CPU):含有运算器和控制器等
- 输出单元:显示器、音响、打印机等
关于冯诺依曼体系结构,需要强调几点:
- 这里的存储器,是指内存
- 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)
- 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取
即所有设备都只能直接和内存交互.
这里我们提出一个问题:为什么要有内存呢?
1.从技术角度:
在计算机的硬件中,cpu
的运算速度 > 寄存器的速度 > L1~L3Cache
三级缓存 > 内存 >> 外设(磁盘) >> 光盘磁带
数据角度:因为外设基本不和cpu
直接交互,而是和内存交互,cpu
也是如此,所以内存在我们看来,就是体系结构的一个大的缓存,用来适配cpu
和外设速度不均的问题.
2.从成本角度:
寄存器成本 >> 内存 >> (磁盘)外设
🌁2.操作系统
概念:任何计算机系统都包含一个基本的程序集合,称为操作系统(OS),笼统的理解,操作系统包括:
- 内核(进程管理、文件管理、内存管理、驱动管理)
- 其他程序(例如函数库、shell程序等)
为什么需要操作系统呢?
- 与硬件交互,管理所有的软硬件资源
- 为用户程序提供一个良好的执行环境
操作系统的定位:
在整个计算机软硬件架构中,操作系统的定位是:一款搞管理的软件
计算机管理硬件的方法:
- 先描述起来,用
struct
结构体 - 再用链表或其他高效的数据结构组织起来
系统调用和库函数概念:
- 在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用
- 系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发
🌠3.进程
在上面,我们了解到操作系统是通过“先描述,再组织”来管理软硬件资源的,那么,操作系统是如何对进程进行管理的呢?
很简单:先把进程描述起来,再把进程组织起来.
3.1 进程基本概念
**进程基本概念:**对于进程的基本概念,在课本上是这样描述的:程序的一个执行实例,正在执行的程序等. 但站在内核的角度:进程就是担当分配系统资源(CPU时间,内存)的实体.
进程 = 可执行程序 + 该进程对应的内核数据结构
3.2 进程控制块-PCB
- 进程信息被放在一个叫做进程控制块的的数据结构中,可以理解为进程属性的集合
- 课本上之为PCB(process control block),Linux操作系统下的PCB是:
这只是Linux内核源码中进程控制块定义的一部分.
在Linux中描述进程的结构体叫做task_struct
.它是Linux内核中的一种数据结构,它会被装载到RAM
(内存)中并且包含着进程的信息.
task_struct
内容分类:
- 标示符: 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
3.3 查看进程
进程的信息可以通过/proc
系统文件夹查看:
例如:要查看PID
为1的进程的进程信息,可以查看/proc/1
这个文件夹
大多数进程信息同样可以使用top
和ps
这些用户级工具来获取.
使用top
命令
ps
命令:
3.4 通过系统调用查看进程标识符
我们可以通过系统调用来获取进程的标识符(用来唯一的标识一个进程),我们可以写这样一段代码:
- 进程
id:pid
- 父进程
id:ppid
运行结果:
3.5 通过系统调用创建进程
我们可以使用系统调用fork
来创建子进程:
-
使用
man fork
认识fork
: -
fork
有两个返回值(给子进程返回0,给父进程返回新建的子进程id
) -
父子进程代码共享,数据各自开辟空间,采用写时拷贝
🌌4. 进程状态
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态,一个进程可以有多个状态.
下面的状态在linux
内核源码中定义:
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
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 */
};
R
运行状态(running)
: 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里
S
睡眠状态(sleeping)
: 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠)
D
磁盘休眠状态(Disk sleep)
有时候也叫不可中断睡眠状态(uninterruptible sleep)
,在这个状态的进程通常会等待IO的结束
T
停止状态(stopped)
: 可以通过发送SIGSTOP
信号给进程来停止(T)
进程。这个被暂停的进程可以通过发送SIGCONT
信号让进程继续运行
X
死亡状态(dead
):这个状态只是一个返回状态,你不会在任务列表里看到这个状态
Z
僵尸状态:一个死进程或“僵尸进程”,这是一个已经终止的子进程,但是它的父进程还没有清空它(父进程没有把子进程从进程表中删除)
4.1 进程状态查看
我们可以使用命令来查看进程的状态:
ps aux / ps ajx
接着,我们可以试着模拟这些进程状态的产生:
-
R
状态(运行状态)使用
ps ajx | head -1 && ps ajx | grep 'mytest' | grep -v grep
组合命令查看进程状态 -
S状态(可中断睡眠)
-
Z状态(僵尸状态)
此时,子进程已经退出,但父进程没有没有等待子进程,子进程进入
Z
状态.
4.2 僵尸进程
- 僵死状态(
Zombies
)是一个比较特殊的状态。当进程退出并且父进程(使用wait()
系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程- 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入
Z
状态
僵尸进程危害:
- 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),可父进程如果一直不读取,那子进程就一直处于Z状态
- 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在
task_struct(PCB)
中,换句话说,Z状态一直不退出,PCB一直都要维护- 一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费
4.3 孤儿进程
父进程先退出,子进程就会变成“孤儿进程”,孤儿进程被1
号init
进程领养,由init
进程回收.
🌿5. 进程优先级
5.1 基本概念
cpu
资源分配的先后顺序,就是指进程的优先级- 优先级高的进程有优先执行权利。配置进程优先级对多任务环境的
linux
很有用,可以改善系统性能- 还可以把进程运行到指定的
CPU
上,这样一来,把不重要的进程安排到某个CPU
,可以大大改善系统整体性能
在Linux或Unix系统中,用ps-l
命令会类似输出以下几个内容:
其中有几个重要信息:
UID
: 代表执行者的身份PID
: 代表这个进程的代号PPID
:代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号PRI
:代表这个进程可被执行的优先级,其值越小越早被执行NI
:代表这个进程的nice
值
5.2 PRI和NI
PRI
也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU
执行的先后顺序,此值越小进程的优先级别越高- 那
NI
呢?就是我们所要说的nice
值了,其表示进程可被执行的优先级的修正数值PRI
值越小越快被执行,那么加入nice
值后,将会使得PRI
变为:PRI(new)=PRI(old)+nice
- 这样,当
nice
值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux
下,就是调整进程nice
值nice
其取值范围是-20
至19
,一共40
个级别
5.3 查看进程优先级的命令
-
使用
top
命令可以查看进程优先级 -
使用
top + r
修改进程的nice
值使用
top
:
按
r
:
输入要修改nice
值的pid
:这里以9949
为例 修改nice
为10:
修改完毕: