文章目录
- 进程
- PCB
- linux查看进程
- 进程属性
- task_struct结构体
- 一、进程标识符
- 父子进程
- 二、进程状态
- 磁盘睡眠 -- D
- 暂停和跟踪暂停 -- T和t
- 僵尸进程 -- Z
- 孤儿进程
- 三、进程优先级
进程
课本概念:程序的一个执行实例,正在执行的程序,操作系统进行资源分配和调度的基本单位等
内核观点:担当分配系统资源(CPU时间,内存)的实体。
linux下,我们使用的命令,如ls等,运行起来就是一个进程。可以说,学习操作系统,首先就要学习进程。
PCB
对于进程,操作系统必要管理它。如何管理?将进程的信息封装为PCB(process control block),通过管理进程的PCB来管理进程。简单来说,PCB是进程属性的集合。
linux查看进程
linux下的进程信息存储在/proc
目录下
大多数的进程信息也可以通过ps和top等用户级工具来获取
ps命令用于显示当前正在运行的进程信息
a
: 显示所有用户的进程。通常情况下,ps命令仅显示与当前终端关联的进程,但使用-a选项可以显示所有用户的进程。
j
: 使用BSD风格的输出格式。这种格式下,ps命令会以进程状态、作业控制信息等形式显示进程信息。
x
: 显示与终端无关的进程。通常情况下,ps命令仅显示与当前终端关联的进程,但使用-x选项可以显示与当前终端无关的进程。
top命令用于动态显示系统中运行的进程的相关信息,包括进程的CPU利用率、内存利用率、进程ID等
进程属性
task_struct结构体
在linux操作系统下的PCB:task_struct(结构体)
task_struct的内容分类:
- 标识符: 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- ……
重点介绍 标识符,状态,优先级
一、进程标识符
进程标识符,即PID:描述本进程的唯一标示符,用来区别其他进程。
这里PPID – parent PID, 即该进程的父进程的PID.
linux也提供了系统接口来获取进程的PID
返回值类型pid_t
, 本质是整型
父子进程
fork()函数是Linux系统中用于创建新进程的一个系统调用。它的作用是创建一个与当前进程几乎完全相同的子进程,这个子进程有着与父进程相同的代码、数据和上下文,但是有着独立的内存空间。
看下方代码:当代码执行到fork()时,进程会生成一个子进程,父子进程共享fork之后的代码,在子进程中ifork返回0,即下方的id = 0
, 在父进程中,fork返回子进程的pid, 即下方id = 19786
,通过之后的if–else语句就可以使父子进程执行不同的代码。如果fork创建子进程失败则会返回-1
二、进程状态
在操作系统理论中,进程一般有3种基本状态:运行、就绪和阻塞。
但上面的只是操作系统理论,实际的操作系统下的进程状态更复杂。
以linux为例,解释一下:运行,阻塞,挂起
在计算机操作系统中,进程可能会由于各种原因而进入阻塞挂起状态,其中包括等待输入/输出(I/O)操作完成、等待系统资源分配、等待进程间通信等。
实际上的linux对进程状态的定义:
R即运行状态,S即阻塞状态,这都好理解,但有3个状态很奇怪:D、T、Z
插一个小知识:我们使用ps命令查看进程会发现有些进程的状态会带个+号,如R+
这里的 +表示该进程是在前台运行
如果在运行时加上&
,可以让程序变为后台运行。此时如果想终止进程则需要kill -9 PID
磁盘睡眠 – D
进程的磁盘睡眠状态(Disk Sleep State)通常是指进程处于等待磁盘I/O操作完成的状态。这种状态通常出现在进程请求进行磁盘读取或写入操作时,但磁盘尚未完成相应的I/O操作,因此进程被阻塞,等待磁盘响应。在这种状态下,进程不会消耗CPU时间,而是被挂起,直到磁盘I/O操作完成。是阻塞挂起状态的一种形式
处于磁盘睡眠的进程,不响应操作系统的请求,直到进程完成它的I/O操作。
要想看到磁盘睡眠,需要进行高I/O操作,不容易演示。可以使用dd
命令来进行,由于dd命令的操作非常强大,但同时也非常底层,因此在使用时需要特别小心,避免造成意外的数据损坏或丢失。
暂停和跟踪暂停 – T和t
Linux操作系统的有个信号kill -19
, 可以使进程暂停。T状态即进程处于暂停状态。注意不要于S状态混淆,S状态一定是进程在等待某种资源,但T状态不一定在等待某种资源。
那T和t有什么区别呢?
Stopped(停止)状态:
进程处于停止状态通常是由于接收到了一个信号,例如SIGSTOP(Ctrl-Z产生的SIGTSTP信号)或者SIGTSTP(通常由shell的暂停命令引发)。这种状态下的进程被挂起,暂时停止执行,但可以通过发送SIGCONT信号来恢复执行。
Tracing Stop(跟踪停止)状态:
进程处于跟踪停止状态通常是由于调试器(如GDB)或者ptrace系统调用的作用。在这种状态下,进程被调试器所追踪,通常是因为调试器在进行单步执行、观察或者修改进程的内存等操作。这种状态下的进程暂时停止执行,直到调试器允许其继续执行。
一般认为T和t没什么区别。
僵尸进程 – Z
当一个进程(子进程)完成执行后,它的退出状态需要被父进程获取。如果父进程没有主动获取子进程的退出状态,那么子进程就会变成僵尸进程,相当于一个人处于生死之间。
下方代码实现:父进程一直运行,子进程执行3次后结束
结果如下:子进程的状态由S+ --> Z+, Z即处于僵尸状态
僵尸进程虽然不会直接对系统造成严重影响,但长时间存在的僵尸进程会对系统的正常运行产生一些间接的危害,包括:可能导致资源耗尽,影响进程管理,降低系统稳定性。因此需要父进程处理僵尸进程。
父进程通常需要调用类似于wait()或waitpid()的系统调用来等待子进程的退出,并获取其退出状态。
当然如果父进程也结束,系统会自动把子进程释放。
孤儿进程
僵尸进程是子进程结束,但父进程未结束。如何父进程先结束,子进程后结束呢?那么子进程便会变为孤儿进程,并被托孤给1号进程,即操作系统。
三、进程优先级
PRI(Priority):PRI 表示进程的静态优先级或调度优先级。俗点说就是程序被CPU执行的先后顺序,此值越小,进程的优先级别越高。
NI(Nice Value):NI 表示进程的 Nice 值,是一个表示进程调度优先级的数值。它的作用是改变PRI的值。
通过PRI和NI可以调整进程的优先级,计算公式如下:
PRI(new)=PRI(old)+nice
’
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值
注意:nice 的范围在 【-20, 19】
PRI(old) 最小是80,如果原来的PRI < 80, 则会直接从80开始算:
因此:PRI 范围【60, 99】,但在计算新的PRI时,最小从80开始
举例:原来 : PRI = 60 NI = 0;
更改:令PRI = 100
结果:PRI = 99 NI = 19
那如何更改nice值呢?
在Linux系统中,nice
命令用于启动一个新的进程,并设置其优先级。而renice
命令用于修改已经运行的进程的优先级。
nice
命令的使用:
nice [OPTION] [COMMAND [ARG]...]
nice
命令通过改变进程的优先级来影响其调度。数值越大,优先级越低。默认情况下,优先级是0。
例如,运行一个命令并设置其优先级:
nice -n <优先级> <命令>
例如,将ls
命令的优先级降低为10:
nice -n 10 ls
renice
命令的使用:
renice [优先级] -p <进程ID> [<进程ID>...]
renice
命令用于修改已经运行的进程的优先级。可以指定一个或多个进程ID来修改它们的优先级。
例如,将进程ID为1234的进程的优先级设置为10:
renice 10 -p 1234
如果你想要提高某个进程的优先级,你需要具有足够的权限。通常,只有超级用户(root)才能提高进程的优先级,而普通用户只能降低自己创建的进程的优先级。