在任何时刻,一个进程要么正在执行,要么没有执行,因而可以构成最简单的模型。
一个进程可以处于以下两种状态之一:运行态或未运行态。在任何一种情况下,分配器都会从队列中选择一个进程来执行。
进程创建的原因:
(1)新的批处理作业;
(2)交互登录;
(3)操作系统因为提供一项服务而创建;
(4)由现有的进程派生。
一个应用程序进程可以产生另一个进程,以接收应用程序产生的数据,并将数据组织成适合以后分析的格式。当一个进程派生另一个进程时,前一个称为父进程,被派生的进程称做子进程
进程终止的原因:
(1)正常完成;
(2)超过时限,指运行时超过时限;
(3)无可用内存;
(4)越界;
(5)保护错误;
(6)时间超出,进程等待超过规定的最大值;
(7)I/O失败;
(8)父进程终止:当一个父进程终止时,操作系统可能会自动终止该进程的所有后代进程。
(9)父进程请求:父进程具有终止其任何后代进程的权力
(10).。。。
5个状态:
(1)运行态:该进程正在执行。
(2)就绪态:进程已经做好了准备,只要有机会就开始运行。
(3)阻塞/等待态:进程在某些事件发生前不能执行,如I/O操作完成。
(4)新建态:指进程控制块已经建好,但是还没有加载到内存中的新进程。
(5)退出态:操作系统从可执行程序中释放的进程
状态间的转换:
5个状态的转换关系如图所示:
(1)空转新建:创建执行一个程序的新进程。
(2)新建转就绪:操作系统准备再接纳一个新进程时。
(3)就绪转运行:需要选择一个新进程运行时,操作系统选择一个处于就绪态的程序,这是调度器(分配器)要做的事情。
(4)运行或退出:如果当前正在运行的进程表示自己已经完成或者取消,则将被操作系统终止。
(5)运行转就绪:正在运行的进程达到了“允许不中断执行”的最大时间段,也可能与进程的优先级有关。
(6)运行转阻塞:必须等待某些事件发生,即表示不能立即获得资源。当进程互相通信,一个进程等待另一个进程提供输入时,或者等待来自另一个进程的信息时,都可能被阻塞。
(7)阻塞态转就绪态:当等待的事件发生后。
(8)就绪转退出:父进程可以在任何时刻终止一个子进程。如果一个父进程终止,那么与父进程相关的子进程都将被终止。
注意:优化方案
1)如果只有一条阻塞队列,当事件发生时操作系统必须扫描整条阻塞队列,搜索那些等待该事件的进程,显然这样效率比较低,如下图所示:
2)如果有多条阻塞模型,一个事件可以对应一条队列,当事件发生时,相应队列中的所有进程都将转换到就绪态,如下图所示。
3)如果按照优先级方案分派进程,维护多个就绪队列(每个优先级一个队列)将会带来很多便利。操作系统可以很容易地确定哪个就绪进程具有最高的优先级且等待的时间最长。
背景:
由于I/O活动比计算机速度慢很多,因此在单道程序系统中的处理器在大多数时候是空闲的,即使是多道程序设计,大多数时候处理器仍然可能处于空闲状态
方案:
方案一:扩大内存以适应更多的进程,不可行。
这种方案有两个缺陷:
首先是内存的价格问题,昂贵;
再者是程序对内存空间的需求,更大的内存往往导致更大的进程,而不是更多的进程
方案二:交换,把某个进程的一部分或者全部移到内存外的磁盘中,可行。
挂起态:
含义: 当内存中的所有进程都处于阻塞态时,
操作系统把其中的一个进程从内存中转移到磁盘里的一种状态。
新增概念:
阻塞/挂起态:进程在外存中,并等待一个事件。
就绪/挂起态:进程在外存中,但是只要载入内存中就可以执行。
状态间的转换:
进程挂起的原因:
交换:操作系统需要释放足够的内存空间,以调入并执行处于就绪态的进程。
其他OS原因:操作系统可能挂起后台进程、工具程序进程或怀疑有问题的进程。
交互式用户请求:用户希望挂起一个程序的执行,为了调试或者与一个资源的使用进行连接。
定时:一个进程可能会周期性的执行(例如监视或系统记账进程),会在等待下一个时间间隔时被挂起。
父进程请求:父进程希望挂起后代进程的执行,以检查或修改挂起的进程,或者协调不同后代进程之间的行为。
分类:
1)R运行状态(running):并不意味着一定在运行中,它表明进程要么是在运行中,要么在运行队列里。
2)S睡眠状态(sleeping):意味着进程在等待事件完成,亦称可中断睡眠(interruptible sleep).
3)D磁盘休眠状态(Disk sleep):也成不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
4)T停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止(T)进程。这个被停止的进程通过发送SIGCONT信号让进程继续运行。
5)X死亡状态(dead):这个状态只是一个返回状态,在任务表中不能看到这个状态。
进程状态的修改 :
1)kill -l//查看系统支持的信号列表
2)kill -SIGSTOP pid//停止进程
kill -SIGCONT pid//运行进程
Z(zombie)——僵尸进程 :
僵死状态是一个比较特殊的状态。当进程退出并且父进程没有读取子进程退出的返回代码时,就会产生僵尸进程 。
代码:
#include
#include
int main()
{
pid_t id = fork();
if (id < 0){
perror("fork");
return 1;
}
else if(id > 0){//parent
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}else{
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}
过程·:父进程睡眠30ms后再运行,子进程睡眠5ms后退出。当子进程退出时,父进程还是睡眠状态,无法读取子进程退出时的返回代码,故子进程将变为僵尸进程
僵尸进程的危害 :
1)进程的退出状态必须被维持下去,因为它要告诉关心它的进程(父进程),你交给我的任务,我完成了怎么样。可是,如果父进程一直不读取,那么子进程将一直处于僵尸进程。
2)一个父进程创建了很多子进程,如果不回收就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,就像C中定义了一个结构体变量(对象),是要在内存的某个位置开辟空间的。
3)造成内存泄露。