进程的定义和PCB
什么是进程?进程就是一个运行起来(也就是说加载到内存)的一个程序。而程序的本质就是文件,当我们写完代码保存,它便形成了一个保存在磁盘上的二进制代码文件。由于冯诺伊曼体系,cpu只和存储进行数据交流,因此要想cpu执行,必须先将外存上的文件载入内存中,而磁盘上文件加载到了内存时也就变成了进程。
PCB:事实上由于在内存中同时运行的进程很多,操作系统需要对所有的进程进行一个统一的管理调度,就例如大学校园里学校将每个学生的学号,姓名,年龄通过excel管理在一张表上,操作系统在内部定义了一个PCB(Process Control Block)进程控制块。 PCB本质上就是一个内核用c语言定义的结构体。 当一个进程进入到内存时,操作系统就对应的创建一个进程控制块PCB对该进程进行管理,每个PCB都有一个唯一的PID。所谓创建进程,其实就是创建PCB。
类似的,PCB将进程的各种特征通过一个struck结构体保存,操作系统通过结构体指针对进程进行操作。类似于:
struct task_struct {
//进程所有属性
//进程所对应的代码和地址
struct tast_struct *next;//指向下一个进程的指针
}
struct tast_struct *p1 = malloc(struct task_struct);
p1->进程属性;
而同时内存为了管理不同的PCB,操作系统创建了一个数据结构对PCB进行管理。将PCB依次首尾相连构建成一个链表。
其好处是,对进程管理就简化成对进程的PCB整个链表进行管理。进程控制就变为了对PCB链表这个内核数据结构的增删查改。
(有的内核版本管理PCB的数据结构可能不是链表,还可以是数组,索引表等数据结构)
如图所示,可以更好的理解PCB,进程,文件之间的关系。进程 = 该进程的代码 + 指向该进程的进程控制块(PCB)。
windows任务管理器就是一个直观的例子。
通过一个例子具体观察一下linux操作系统中的进程,我们可以编写一个可执行程序myproc,让它显示自己的pid:
此时我将它保存,它成为一个保存在磁盘上的一个文件而已,并没有进入内存,因此并不是进程:
通过make编译形成可执行文件,再运行该可执行文件,它就形成了一个内存上的进程:
关闭进程再开启时,进程pid会改变。
此时,在操作系统下有一个/proc目录,目录下所有子目录名均为数字,每个数字都代表一个进程的PID。很显然,进程在操作系统内核中是以文件显示出来的。
每当新进程加载进入内存时,操作系统都会在/proc目录下创建一个目录名为进程PID的文件夹,同理,退出进程会将其对应的目录删除。我们找到目录名为3271的目录,也就是我上面所执行的进程的PID:
其指向的路径是磁盘上我刚创建的可执行程序。