进程
什么是进程
进程是一个具有独立功能的程序关于某个数据集合的一次可以并发执行的运行活动。
与程序的关系:
程序是一个普通文件,是机器代码指令和数据的集合,这些指令和数据存储在磁盘上的一个可执行映像中。所谓可执行映像就是一个可执行文件的内容。
进程代表程序的执行过程,它是一个动态的实体,随着程序中指令的执行而不断地变化。在某个时刻进程的内容称为进程映像。
与程序的区别:
(1)程序是保存在磁盘上的可执行代码和数据的映像;进程是正在运行的程序。
(2)一个程序可以同时有多个进程实例,它们互相没有关系。
(3)存在磁盘上的程序是静态的,而执行中的进程则是动态的。
进程状态
不同操作系统中进程状态的种类数量和命名一般会不相同,但最基本的进程状态有三种:
(1)运行态:进程占有CPU,并在CPU上运行。
(2)就绪态:进程已经有运行条件,但由于CPU忙而暂时不能运行。
(3)阻塞态:进程因等待某种事件的发生而暂时不能运行,也称为等待态。
进程在生命周期内的任意时刻处于且仅处于三种基本状态之一。上述三种状态进行切换时有如下四种转换关系:
(1) 运行态→阻塞态:当进程内发生I/O请求或等待某件事情的发生,使进程无法运行下去时发生这种转换。
(2)运行态→就绪态:当进程用完操作系统给它分配的时间时发生这种转换。
(3)就绪态→运行态:当操作系统给该进程分配了CPU时,调度进程就从就绪态的进程选择一个投入运行。
(4)阻塞态→就绪态:当进程等待的事件发生后具有可运行条件时,就发生这种转换。
调度进程的主要工作是决定当前应该运行哪个进程,以及它应该运行多长时间。
进程实例
Linux中,用户在程序中可以通过fork系统调用来创建进程,调用进程叫父进程parent,被创建的进程叫子进程child。
<span style="font-family:Times New Roman;font-size:24px;">#include <sys/types.h> /*提供pid_t类型的定义,与int类型相同*/
#include <unistd.h> /*提供系统调用的定义*/
int main()
{
pid_tpid;
printf("PIDbefore fork(): %d\n", (int)getpid());
pid= fork();
if(pid < 0)
printf("createfailed\n");
else if( pid == 0)
printf("thisis child process, the PID is %d\n", (int)getpid());
else
printf("thisis parent process, the PID is %d\n", (int)getpid());
return0;
}</span>
程序运行结果:
PID before fork(): 5323
this is parent process, the PID is 5327
this is child process, the PID is 5328
fork创建新的进程,调用fork的是父进程,新创建出来的子进程与父进程几乎是一样的,只有少量属性不同,比如PID。调用fork一次,有两次返回。子进程的返回值为0,父进程的返回值是一个正整数,是子进程的PID。
进程控制块
为了对进程进行管理,操作系统必须要对每个进程在其生命周期内涉及的所有事情进行记录,比如进程状态、优先级、地址空间等等,所有的信息在内核中用一个结构体来描述,Linux中把这个结构称为task_struct。
传统中这数据结构叫进程控制块PCB,其内容多达80多项,不过按照功能可分为以下几类:
(1)状态信息 描述进程的动态变化
(2)链接信息 描述进程的父/子关系
(3