那么就说明exec执行失败了,为什么它会执行失败呢?因为现在主进程如果被覆盖,那么它的数据段就会释放,但是此时轻权进程还要继续使用这个数据段,会发生错误,所以主进程无法被覆盖。要使exec能够执行成功,第一可以使轻权进程在主进程被覆盖前就执行完毕,第二可以使轻权进程通过exec升级成为一个普通进程,第三可以使用fork来创建子进程。我们修改程序,用getch()使主进程等待直到轻权进程执行完毕。
执行结果如下:
果然,轻权进程结束后,主进程执行exec成功创建新进程覆盖了主进程。
用do 1 1将上面的程序执行两个进程,结果过如下:
发现在这个过程中当打印第一行a的时候进程监视器显示进程1在执行,进程2是就绪态,但是当第一行a输出完了显示的还是进程1在执行,进程2没有了。那么难道第一行a是进程2创建的新进程输出的?,但是这个过程中进程1才是处在执行态。我们来分析一下过程:首先进程1和2的轻权进程都执行完,进程1的getch()收到了输入的消息,执行exec创建一个新的进程覆盖原来的进程1,这个新的进程的进程号就是1,然后它执行输出,执行完毕后结束,这时就只有处于就绪态的进程2了,进程2执行exec创建一个新的进程,因为之前的进程1不存在了,所以这一个新的进程的进程号就是1,所以我们才会看到进程1一直处于执行态。
五、进程间的通信我们可以用fork、frk、cobegin函数创建多个进程并使它们并发执行,进程的执行需要一些资源,那么当多个进程并发执行时要使用相同的资源怎么办?我们把一个全局变量当作资源,设计两个进程都对这个全局变量进行操作:
执行结果如下:
如果这两个进程并发执行的话,第一个进程先使用资源,对a加1并输出,那么先输出的应该是a=1,第二个进程输出的是a=2。为什么这两个进程输出的都是a=2呢?因为f1中有延时函数delay(50),在f1延时时f2的进程对a加了1,所以f1输出a的时候a的值已经变成了2.也就是说f1和f2的进程并发执行有可能导致f1和f2的公共资源使用出错。那么怎么解决这个问题呢?要得到正确的结果,就要让一个进程的执行过程中不会被其他进程所干扰,形成进程互斥。即让一个进程的执行内容像一个原子操作,具有原子性。
我们可以使用PV原语来保证进程的原子性,PV原语是对于信号量的操作,信号量的值代表有几个资源,P操作是将信号量减1,如果执行后信号量大于等于0,就继续执行,否则将该进程堵塞并置于该信号量的阻塞队列中。V操作是对信号量加1,如果执行后信号量的值大于0,那么就将继续执行,否则从该信号量的等待队列中唤醒一个等待的进程。也就是说,P操作是将当前进程由运行态转为阻塞态,而V操作是将一个阻塞态的进程转成就绪态。而他们对进程的阻塞和唤醒是根据当前信号量的值来判断的,因为���号量的值就代表了当前资源的数目。
我们使用PV操作来对上面的程序进行修改:
执行结果为: