1. 进程定义
进程是操作系统理论的核心与基础,操作系统中的许多概念都和进程相关。
进程的定义 ,进程有过各种各样的定义,现列举较为著名的几种。
进程是一个独立的可调度的活动;
进程是一个抽象实体,当它执行某个任务时,要分配和释放各种资源;
进程是可以并行执行的计算单位;
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动;
进程是一个程序的一次执行过程,同时也是资源分配的最小单元。
进程和程序是有本质区别的:
程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念;
而进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和消亡的整个过程;
它是程序执行和资源管理的最小单位。
2. 进程分类
Linux操作系统包括三种不同类型的用户进程,每种类型的进程都有自己的特点和属性。
(1) 交互进程——由shell启动的进程。交互进程既可以在前台运行,也可以在后台运行。
(2) 批处理进程——这种进程和终端没有联系,它是被提交到一个队列中的进程序列。
(3) 守护进程——又称监控进程,也就是通常说的Daemon进程,是Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。
3. 进程控制块(PCB)
Linux系统通过进程控制块来描述一个进程。
进程控制块包含了进程的状态信息、控制信息以及资源信息等。
进程控制块是进程存在的标志,每一进程都有一进程控制块,Linux中用数据结构task_struct表示,并将指向每个进程控制块的指针保存在数组task中。
task_struct 结构中包含了许多字段,按照字段功能,可分成如下几类:
进程控制块
(1) 标识号。每个进程都有一个进程标识号(PID)和一个父进程标识号(PPID),其中PID唯一标识一个进程。另外,一个进程还有自己的用户标识号(UID)和组标识号(GID),系统通过这两个标识号判断进程对文件或设备的访问权。
(2) 状态信息。一个 Linux 进程可有如下几种状态:运行、等待、停止和僵死。
(3) 调度信息。调度器根据这些信息判定系统中哪个进程最迫切需要运行。
(4) 有关进程间通讯的信息。系统利用这一信息实现进程间的通讯。
5) 进程与其他进程之间的关系信息:在 Linux 系统中,除根进程之外,任何一个进程都具有父进程也可能有兄弟进程或子进程。所以每个进程的PCB中包含了进程的父进程指针、和该进程具有相同父进程的兄弟进程指针以及进程的子进程指针。另外,Linux 还利用一个双向链表记录系统中所有的进程,这个双向链表的根就是 init 进程。利用这个链表中的信息,内核可以很容易地找到某个进程。
(6) 时间和定时器信息。系统在这些字段中保存进程的建立时间,以及在其生命周期中所花费的 CPU 时间。Linux 也支持和进程相关的定时器,应用程序可通过系统调用建立定时器,当定时器到期,操作系统会向该进程发送sigalrm信号。
(7)文件系统信息。这类字段记录进程所打开的文件描述符信息。另外,还包含指向虚拟文件系统(Virtual File Systems,VFS)两个索引节点的指针,这两个索引节点分别是进程的主目录以及进程的当前目录。索引节点中有一个引用计数器,当有新的进程指向某个索引节点时,该索引节点的引用计数器会增加。未被引用的索引节点的引用计数为 0,因此,当包含在某个目录中的文件正在运行时,就无法删除这一目录,因为这一目录的引用计数大于0。
(8)虚拟内存与物理内存相关信息:每个进程均有自己的内存空间,为了让linux内核随时了解和控制进程的内存空间,PCB中必须保存进程内存空间的相关信息。
(9)和进程相关的上下文信息。进程上下文是用来保存进程相关的系统状态的字段。当调度程序将某个进程从运行状态切换到暂停状态时,会在上下文中保存当前的进程运行环境,包括 CPU 所有寄存器的值、进程的状态以及堆栈信息;当调度程序再次选择该进程运行时,则会从进程上下文信息中恢复进程的运行环境。
进程上下文
所谓的进程上下文,就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容,当内核进行进程切换时,需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
4. 进程标识符
在Linux中最主要的进程标识:
进程号(PID,Process Idenity Number)
父进程号(PPID,parent process ID)。
其中PID惟一地标识一个进程,内核通过这个标识符来识别不同的进程,用户程序通过PID对进程发号施令。
PID和PPID都是是32位的无符号整数
进程标识还有用户和用户组标识、进程时间、资源利用情况等
在Linux中获得当前进程的PID和PPID的系统调用函数为getpid()和getppid()。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() { printf("The PID of this process is %d \n",getpid()); printf("The PPID of this process is %d \n",getppid()); return 0; }
Linux中的运行截图:
5. 进程运行的状态
进程是程序的执行过程,根据它的生命周期可以划分成5种状态(前3种为基本状态)。
执行态:该进程正在运行,即进程正在占用CPU。
就绪态:进程已经具备执行的一切条件,正在等待分配CPU的处理时间片。
等待态:进程正在等待某个事件或某个资源。等待态又分为可中断等待和不可中断等待两种。可中断的等待进程可被信号中断,而不可中断的等待进程不能被信号中断。
停止状态:当进程收到一个SIGSTOP信号后,便由运行态进入停止状态,当收到SIGCONT信号时又会恢复运行态,该状态主要用于调试。
僵死状态(终止状态):进程已终止,但其task_struct 结构仍在内存中。顾名思义,处于这种状态的进程实际是死进程。
进程运行的状态如下:
进程的各种基本状态及其转换:
注: Linux下编译运行C程序详解参考博客, (实训第一天)Linux下编译运行C源程序的过程(图解)