进程和程序的区别
程序
程序本质上是一系列二进制信息,这些信息描述了如何在运行时创建一个进程:
- 二进制格式标识:每个程序文件都包含用于描述可执行文件格式的元信息。内核利用此信息来解释 文件中的其他信息。
- 机器语言指令。
- 程序入口地址:标识程序开始执行时的起始指令位置。
- 数据:程序文件包含的变量初始值和程序使用的字面量值(比如字符串)。
- 符号表及重定位表:描述程序中函数和变量的位置及名称。这些表格有多重用途,其中包括调试和 运行时的符号解析(动态链接)。
- 共享库和动态链接信息:程序文件所包含的一些字段,列出了程序运行时需要使用的共享库,以及 加载共享库的动态连接器的路径名。
- 其他信息:程序文件还包含许多其他信息,用以描述如何创建进程。
进程
- 进程是正在运行的程序的实例。是一个具有独立功能的程序,包含运行时所需的各种资源。
- 它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的 执行单元。
- 可以用一个程序来创建多个进程,进程是由内核定义的抽象实体,并为该实体分配用以执行程序的 各项系统资源。
- 从内核的角度看,进程由用户内存空间和一系列内核数据结构组成,其中用户内存空间包含了程序 代码及代码所使用的变量,而内核数据结构则用于维护进程状态信息。记录在内核数据结构中的信 息包括许多与进程相关的标识号(IDs)、虚拟内存表、打开文件的描述符表、信号传递及处理的 有关信息、进程资源使用及限制、当前工作目录和大量的其他信息。
- 对于一个单 CPU 系统来说,程序同时处于运行状态只是一种宏观上的概念,他们虽然都已经开始 运行,但就微观而言,任意时刻,CPU 上运行的程序只有一个。
- 在多道程序设计模型中,多个进程轮流使用 CPU。而当下常见 CPU 为纳秒级,1秒可以执行大约 10 亿条指令。由于人眼的反应速度是毫秒级,所以看似同时在运行。
单道和多道程序设计
- 单道程序,即在计算机内存中只允许一个的程序运行。
- 多道程序设计技术是在计算机内存中同时存放几道相互独立的程序,使它们在管理程序控制下,相 互穿插运行,两个或两个以上程序在计算机系统中同处于开始到结束之间的状态, 这些程序共享计 算机系统资源。引入多道程序设计技术的根本目的是为了提高 CPU 的利用率。
- 对于一个单 CPU 系统来说,程序同时处于运行状态只是一种宏观上的概念,他们虽然都已经开始 运行,但就微观而言,任意时刻,CPU 上运行的程序只有一个。
- 在多道程序设计模型中,多个进程轮流使用 CPU。而当下常见 CPU 为纳秒级,1秒可以执行大约 10 亿条指令。由于人眼的反应速度是毫秒级,所以看似同时在运行。
并行和并发
并行
并行(parallel): 指在同一时刻,有多条指令在多个处理器上同时执行。
并发
并发(concurrency): 指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使 得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干 段,使多个进程快速交替的执行。
进程控制块(PCB)
为了管理进程,内核必须对每个进程所做的事情进行清楚的描述。内核为每个进程分配一个 PCB(Processing Control Block)进程控制块,维护进程相关的信息,Linux 内核的进程控制块是 task_struct 结构体。
Linux中的PCB包括以下信息:
- 进程id:系统中每个进程有唯一的 id,用 pid_t 类型表示,其实就是一个非负整数
- 进程的状态:有就绪、运行、挂起、停止等状态
- 进程切换时需要保存和恢复的一些CPU寄存器
- 描述虚拟地址空间的信息
- 描述控制终端的信息
- 当前工作目录(Current Working Directory)
- umask 掩码(创建文件或目录的默认权限)
- 文件描述符表,包含很多指向 file 结构体的指针
- 和信号相关的信息
- 用户 id 和组 id
- 会话(Session)和进程组
- 进程可以使用的资源上限(Resource Limit)
5 进程的状态
在三态模型 中,进程状态分为三个基本状态,即就绪态,运行态,阻塞态。在五态模型中,进程分为新建态、就绪 态,运行态,阻塞态,终止态。
- 运行态:进程占有处理器正在运行
- 就绪态:进程具备运行条件,等待系统分配处理器以便运行。当进程已分配到除CPU以外的所有必 要资源后,只要再获得CPU,便可立即执行。在一个系统中处于就绪状态的进程可能有多个,通常 将它们排成一个队列,称为就绪队列
- 阻塞态:又称为等待(wait)态或睡眠(sleep)态,指进程不具备运行条件,正在等待某个事件的完成
- 新建态:进程刚被创建时的状态,尚未进入就绪队列
- 终止态:进程完成任务到达正常结束点,或出现无法克服的错误而异常终止,或被操作系统及有终 止权的进程所终止时所处的状态。进入终止态的进程以后不再执行,但依然保留在操作系统中等待 善后。一旦其他进程完成了对终止态进程的信息抽取之后,操作系统将删除该进程。
进程相关指令
查看进程
1 | ps aux / ajx |
STAT参数意义:
1 | D 不可中断 Uninterruptible(usually IO) |
实时进程动态
1 | top |
可以在使用 top 命令时加上 -d 来指定显示信息更新的时间间隔,在 top 命令执行后,可以按以下按键 对显示的结果进行排序:
- M 根据内存使用量排序
- P 根据 CPU 占有率排序
- T 根据进程运行时间长短排序
- U 根据用户名来筛选进程
- K 输入指定的 PID 杀死进程
杀死进程
kill并不是去杀死一个进程,而是给进程发送某个信号
1 | kill [-signal] pid |
1 | kill –l 列出所有信号 |
1 | kill –l |
数字9为SIGKILL
kill –SIGKILL 进程ID
和 kill -9 进程ID
等价,也可根据名字来杀死进程:killall name 根据进程名杀死进程
进程号相关函数
每个进程都由进程号来标识,其类型为 pid_t(整型),进程号的范围:0~32767。进程号总是唯一
的,但可以重用。当一个进程终止后,其进程号就可以再次使用。
任何进程(除 init 进程)都是由另一个进程创建,该进程称为被创建进程的父进程,对应的进程号称为
父进程号(PPID)。 进程组是一个或多个进程的集合。他们之间相互关联,进程组可以接收同一终端的各种信号,关联的进
程有一个进程组号(PGID)。默认情况下,当前的进程号会当做当前的进程组号。 进程号和进程组相关函数:
1 | pid_t getpid(void); |
1 |
|
进程创建
系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。除了
1 |
|
返回值:
成功:子进程中返回 0,父进程中返回子进程 ID 失败:返回 -1
失败的两个主要原因:
当前系统的进程数已经达到了系统规定的上限,这时 errno 的值被设置为 EAGAIN 系统内存不足,这时 errno 的值被设置为 ENOMEM
1 | /* |