我们在上一个程序执行的过程中发现,我们在执行程序后程序的内容还没有开始执行,这时进程监视器显示进程处于ready就绪态,在我们输入一个字符后进程就进入了运行态,运行完毕后退出,也就是说进程在程序开始是就绪态,之后进入运行态,运行完毕后从运行态退出,即进程的起点是就绪态,终点是运行态,我们来看看这三种状态的具体含义:
1、就绪态:进程分配到除CPU以外的所有资源,只要能获得cpu就能执行。
2、执行态:进程获得cpu正在执行。
3、阻塞态:进程因等待某事件而暂停执行。
所以,我们调用一个程序,就创建了一个进程,这时进程分配了所要的内存空间等资源,但是这时还有没执行,因为没有cpu来计算进程的数据得到结果。如果进程分配到了cpu资源就开始执行,进入运行态,如果这时进程执行过程中要等待某事件才能继续执行,比如要用户进行输入,就会进入阻塞态,即处于暂停的状态,直到事件发生,但是这时cpu还在执行其它进程的计算任务,所以这个进程进入到就绪态,直到分配到cpu的资源再进入执行态继续执行。也就是说,就绪态和阻塞态都是缺少一些东西,就绪态是缺少cpu资源,阻塞态是缺少某件事情的发生,只有运行态是具备一切条件,可以顺利执行程序的,所以在正常情况下运行态是进程的出口。
那么为什么进程要从就绪态开始进入,而不是阻塞态进入呢?因为我们在执行程序后,创建进程并分配好所需的一切资源,这时候是不可能缺少外部的事件的,只有当程序开始执行后,才会需要某些事件的发生。也就是说,就绪态需要的是内部资源,即cpu资源,而阻塞态需要的是外部资源,即某些事件的发生。所以在正常情况下就绪态是进程的入口。
所以我们在执行do 1 1时会发现进程1、2在运行态和就绪态之间相互转化,这说明两个进程在交替使用cpu资源。如果一个处于执行态在使用cpu资源,那么另一个就处于就绪态在等待cpu资源。
我们在程序中加入一个getch函数:
执行结果如下:
当程序执行到getch()时等待键盘输入,我们看到这时进程的状态还是运行态,这是为什么呢?为什么这时是等待外部事件发生,但是进程没有转到阻塞态?查询函数手册可知,getch函数是调用进程循环等待,不会使进程进入阻塞态,而get_char会使进程进入阻塞态来等待输入,我们把程序里的getch换成get_char函数执行来看看结果:
可以看到此时的进程处于阻塞态来等待输入。
所以我们在使用相关函数时要注意它是否是一个阻塞函数,要注意阻塞和循环等待的区别。类似的函数还有gets和get_str、wait和sleep等。要注意我们使用get_str时在进行键盘输入就会唤醒进程,即让进程从阻塞态进入运行态,那么对于阻塞的进程,除��进程需要的事件发生,可以用其他的方式将进程唤醒吗?查询函数手册可知wakeup函数为唤醒原语,那么可以用wakeup函数唤醒阻塞的进程吗?我在上面程序的getch()改成get_char后调用wakeup函数,结果发现没有起作用,这是因为进程在执行get_char函数后就进入了阻塞态,这时程序不往下执行,所以不会执行wakeup语句。但是因为wakeup是唤醒原语,所以要唤醒一个进程一定会使用它,但是可能是在get_char函数中调用,这涉及到进程的三态模型是通过什么来控制的,进程是操作系统执行程序的一种方式和过程,所以是操作系统控制进程在三种状态之间转换。
我们可以体会一下三态模型的思想:进程执行需要一些外部的操作和内部的资源,就绪态是缺少内部的资源(cpu),这是内因,阻塞态是缺少外部的资源(事件的发生),这是外因,当内因和外因都具备时就可以转到运行态执行了。在这里,cpu资源是最宝贵的,它直接决定了计算机和程序的运行速度,所以进程思想和三态模型的出现都是为了最大程度地分配和利用cpu资源。
四、进程的创建