进程是什么?
进程是现代计算机体系的重要概念,了解进程前必须知道计算机的运行方式与操作系统这两个概念(本文仅做概念引入,若想深入了解可以阅读《计算机导论》)
-
冯诺依曼体系结构让我们知道计算机的核心是CPU,它承担了所有的计算任务; -
而操作系统就是计算机的管理者,负责任务的调度,资源的分配和管理; -
为了在计算机上实现某种功能,程序员设计了一系列运行在操作系统上的应用程序; -
从微观上看,这些程序在计算机上运行的就是一条一条带有某种使命的进程。
1. 冯诺依曼体系结构
当今计算机运行的基本方式都是建立在冯诺依曼体系结构之上。
所谓冯诺依曼体系,就是将计算机分为了五个部分:CPU(运算器、控制器)、储存器、输入、输出设备; 注:这里的储存器指内存,而非硬盘.
并提出了计算机制造的三个原则:
- 二进制:计算机处理的数据和指令一律用二进制数表示;
- 程序存储:指令和数据不加区别混合存储在同一个存储器中;
- 顺序执行:顺序执行程序的每一条指令;
2. 操作系统OS
操作系统是什么?
一个用户无法直接与计算机硬件打交道,必须有个有一个 中介 方便用户对计算机的使用,这个中介就是操作系统(OS);
操作系统本质上就是一个协调、管理和控制计算机硬件资源和软件资源的控制程序;
因此我们也可以简单的认为:
-
操作系统 = 操作系统内核 + 应用
内核:指计算机中进行进程、文件、内存、驱动管理的程序
应用:附加在OS上为了实现用户目的的一些软件应用
操作系统做什么?
由定义可知,操作系统就是一个管理计算机软硬件资源的软件。
硬件资源:CPU、内存、硬盘、IO接口… 软件资源:进程资源、驱动程序…
这里引入 进程 的概念,计算机执行一项任务的基本单位就是进程。大量进程在计算机中运行,就必须要协调管理,这个任务就是OS要做的事。
操作系统的管理方式
OS管理进程方式:描述 + 组织
- 描述:通过结构体描述一个进程(PCB)
- 组织:串联结构体
OS组织结构图:
tip:系统调用函数&库函数
3. 进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体.
进程组成
- 进程一般由程序,数据集合和进程控制块三部分组成。
即:进程 = 内核数据结构(PCB) + 该程序的代码 + 数据集合
进程与程序的区别?
- 程序是代码编译后的静态文件
- 进程是正在运行的动态实例
进程控制块(PCB)详解
进程控制块(process ctrl block)是操作系统为了管理进程设置的一个专门的结构体 task_struct。
操作系统用它来记录进程的外部特征,描述进程的运动变化过程。同时,系统可以利用PCB来控制和管理进程。
那么进程控制块(即 task_struct结构体)都包含了哪些信息?
1. 进程号pid
概念
- 这是当前OS中每个进程唯一的标识符
- PID是一个正整数,取值范围从2到32768
可以通过:cat /proc/sys/kernel/pid_max 查看系统支持多少进程
- 当一个进程被启动时,OS会顺序挑选下一个未使用的编号数字做为该进程的PID
- 进程号可以重复使用:
即一个进程结束后,该进程的进程号会被OS回收并再发放给另一个要运行的进程。
Linux操作系统的进程与PID
Linux中查看进程:
例:
#include <stdio.h>
#include <unistd.h>
int main()
{
while(1)
{
printf("my pid is %d\n",getpid());
sleep(3);
}
return 0;
}
2. 进程状态
进程的三种基本状态
-
就绪(Ready)状态
进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行
-
执行(Running)状态
进程已获得CPU,其程序正在处理机上执行
-
阻塞(Blocked)状态
正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。
引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。
进程的抢占式执行
【注意】这三种进程状态的转换并不是任意的:
进程状态细分
现代OS对进程状态的划分不止上述三种,更加的具体:
1. 运行状态:R
运行状态(TASK_RUNNING):运行态和就绪态的合并,表示进程正在运行或准备运行。 要想观察一个进程的运行状态,就不能让这个进程return 0,因此可以为进程加一个while死循环;但是注意,这个循环内不能有sleep(),因为一旦调用了sleep,进程就可能处于水睡眠状态
2. 可中断睡眠状态:S
可中断睡眠状态(浅度睡眠)(TASK_INTERRUPTIBLE):进程正在睡眠(被阻塞),当等待资源到来时即可唤醒,也可以通过其他进程信号或时钟中断唤醒,进入运行队列。
3. 不可中断睡眠状态:D
不可中断睡眠状态(深度睡眠状态)(TASK_UNINTERRUPTIBLE):其和浅度睡眠基本类似(也在阻塞),但有一点就是不可被其他进程信号或时钟中断唤醒。
4. 暂停状态:T
暂停状态(TASK_STOPPED):进程暂停执行接受某种处理(进程被挂起,不是阻塞态)。 向进程发送一个SIGSTOP信号(Ctrl+Z),它就会因响应该信号而进入暂停状态
5. 跟踪状态:t
跟踪状态(TASK_TRACED):一个正在调试的进程就是跟踪状态。
6. 僵尸状态:Z(后续详讲)
僵尸状态(TASK_ZOMBIE):一个进程已经结束但未释放PCB。这是一种不正常的进程状态,编程中应避免这样的情况。
如果了解父子进程的概念,就知道如果一个子进程在父进程结束之前先退出,父进程会忽略子进程发给父进程的退出信号,从而无法让子进程的PCB释放。
僵尸进程甚至无法通过kill -9强杀命令杀死 ,具体细节见下一篇博客~
7. 死亡状态:X
死亡状态(TASK_DEAD):一个进程即将退出,PCB随之也会销毁。所以死亡状态是非常短暂的,几乎不可能通过ps命令捕捉到(仅作概念了解)。
进程状态与Linux指令
-
一个普通的死循环进程mytest ,通过指令ps aux | grep mytest 可以看到该进程为R运行状态; R+ 表示在前台执行的进程,任何进程状态后跟 + 表示在前台,- 表示在后台。 -
为代码的循环中加一个sleep() 函数,即可看到进程为S睡眠状态; -
通过指令kill -[进程号] 或Ctrl + C(必须在当前执行窗口) 即可退出运行态或睡眠态的进程; -
运行或睡眠的进程通过指令kill -STOP [PID] 或Ctrl + Z(必须在当前执行窗口) 即可将此在前台执行的进程放到后台,挂起暂停(T暂停状态); -
在已挂起进程的窗口中输入指令jobs ,可以显示当前目录下的任务列表及任务状态,包括后台运行的任务; -
如何唤醒正在挂起的进程? 通过指令fg [jobID] 可将进程放到前台并唤醒; 通过指令bg [jobID](或kill -CONT [pid]) 可将进程放到后台并唤醒; -
kill -[进程号] 或Ctrl + C 对于挂起进程无效!挂起进程只能通过进程强杀指令kill -9 [pid] 退出; -
kill -[进程号] 或Ctrl + C 对于僵尸进程无效 !通过进程强杀指令kill -9 [pid] 也无效。
3. 其他内容
|