进程的概念:进程是一个具有一定独立功能的程序在某个数据集上的一次运行活动。
一. 进程的一些特性
(1)动态性:进程因创建而产生,由“撤销”而消亡,因“调度”而运行,因“阻塞”而停顿。进程由创建到消亡称为进程的声明周期;
(2)并发性:同一时间段内有多个进程在系统中活动;
(3)独立性:进程是可独立运行的基本单位,是操作系统资源分配和调度的基本单位;
(4)异步性:每个进程都独立地执行,各自按照不可预知的速度向前推进。
二. 进程的基本状态及转换
1. 进程的三个基本状态:运行,就绪,阻塞。
(1)就绪态:进程已经分配到了除CPU外的所有资源,一旦获得CPU便可执行。
(2)运行态:进程已经获得CPU ,正在运行。
(3)阻塞态:进程由于某种资源不能满足,或者希望的某事件尚未发生而暂停执行。
2.进程状态的转换
进程在诞生之初是处于就绪状态。
(1)运行------>阻塞:正在执行的进程因为等待某事件而无法执行下去,如I/O请求。
(2)阻塞------>就绪:处于阻塞态的进程,其所申请的资源得到满足,转为就绪态。
(3)运行------->就绪:正运行的进程时间片用完时,或者更高优先级的进程到来时,系统暂停该进程运行,进入就绪态。
(4)就绪-------->运行:处于就绪态的进程,被进程调度程序选中后,即进入CPU运行,变为运行态。
三. 进程的运行模式
Linux内核运行在核心态,而用户程序只能运行在用户态。从用户态转化为核心态的唯一途径就是中断或系统调用。CPU响应中断后将CPU状态切换到核心态,中断处理结束后,返回用户态。在进行通常的计算和处理时,进程运行在用户态;执行系统调用或中断处理程序时进入核心态,执行内核代码。
Linux内核负责最基本的资源管理和硬件控制工作,为进程提供运行环境,并提供内核函数(即系统调用)供进程使用。
Linux 内核主要由系统调用接口、进程管理子系统、文件与I/O子系统、硬件控制接口等部分组成。
四、进程控制
进程控制即对进程的生命周期进行有效的管理,实现进程的创建、撤销和进程各状态之间的转换控制功能。
1、进程的创建与映像更换
系统的所有进程都是由1号进程init进程创建的子孙进程。
(1)创建进程
fork()与vfork()函数,为子进程建立资源描述结构,并将父进程的资源描述复制过来,fork()返回后,子进程就 绪,等待进程调度。之后父子进程并发执行,执行同一个代码映像,拥有各自的执行环境,互不影响,子进程从fork()返回位置执行,其前的代码无法执行。注意,父子进程谁先获得CPU并不一定。
(2)读时共享、写时拷贝
Linux系统中,当fork()完成后并不立刻复制父进程的映像内容,而是让子进程共享父进程的同一份拷贝,直到有一方执行写入操作是才进行复制,使父子进程拥有各自独立的拷贝。这就是读时共享写时拷贝技术。
2、进程的终止与等待
(1)进程终止运行的两种方式:
第一种是在程序中使用退出语句主动终止运行,如return和exit();另一种是被某个信号杀死。
进程无论以哪种方式退出都会调用exit()系统调用,其完成以下操作:释放进程所有资源,只保留PCB和内核栈;向PCB写入进程退出信息;将自己的子进程(如果有)交给其他进程或者init进程,向父进程发送SIGCHLD信号;设置进程状态为“僵死态”;调用进程调度程序切换进程。此时,进程不再具备执行条件,仅存PCB和内核栈。
(2)进程的等待与回收
先理解僵尸进程与孤儿进程:
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
僵尸进程占用系统的重要资源,必须将其消除,其回收工作一般由父进程负责,采用wait()或waitpid()系统调用函数等待子进程结束。
其中wait(status)函数的传出参数保存了进程退出的状态,可以借助宏函数进一步判断进程终止原因。这里给出几个常用的宏函数:
1、WIFEXITED(status)为非零,表明进程正常结束。配对使用的是:如果前述函数为真,使用WEXISTATUS(status)获取进程退出状态(exit函数的参数)
2、WIFSIGNALED(status)为非零,进程异常结束。配对使用的是:如果前述函数为真,使用WTERMSIG(status)获得使进程终止的那个信号的编号。