第2章 进程管理

来源:互联网 发布:2016access数据库教程 编辑:程序博客网 时间:2024/05/17 01:13

进程概念的引入

从静态角度看,进程PCB、程序段和数据空间三部分组成,用户可通过函数调用建立和撤消进程,通常用户进程被建立后,随着作业运行正常或不正常结束而撤消。

PCB是进程存在的唯一标志,存放进程的特征和变化过程及控制进程所需的所有数据, 是进程控制和调度的依据和操作对象。
PCB中的内容:进程标识符、处理器状态 、调度信息、控制信息

项目 进程 程序 动态性 动态的(进程是程序的执行) 静态的(程序是有序代码的集合) 并发性 √ ×(因为没有PCB) . 独立、异步 静态的文件

具有挂起操作的进程状态转换图

这里写图片描述

P、V操作

  • 临界资源:一次仅允许一个进程访问的资源,
  • 临界区: 并发进程中访问临界资源的程序段

有m个进程共享同一临界资源,若使用信号量机制实现对临界资源的互斥访问,则信号量值的变化范围是1 ~ -(m-1)。

  • 两个原子操作:
    P操作 wait(S):请求一个单位的资源;
    若减1后S.value < 0,则表示资源已分配完毕。故进程调用block原语进行自我阻塞,
    并被插入到等待队列尾。
    V操作 signal(S):释放一个单位的资源;
    若加1后S.value <= 0,则表示等待队列中仍有进程等待该资源。故进程调用wakeup原语唤醒位于队首的那个进程。

生产者 - 消费者问题:

一组生产者进程生产产品给一组消费者消费。为使他们并发执行,设有一个n个缓冲区的缓冲池,生产者一次向一个缓冲区投入消息,消费者从一个缓冲区中取得消息。

int in=0, out=0;            //放入和取出的数据地址item buffer[n];             //缓冲池semaphore mutex = 1,        //            empty = n,        //缓冲池中 空缓冲区的数量            full = 0;       //       满缓冲区的数量void proceducer(){    do{        ...        //生产者生产一个产品nextp;        ...                     wait(empty);        //传说中的P操作(empty-1)        wait(mutex);//------------请求锁------------        buffer[in] = nextp;        in = (in+1) % n;        signal(mutex);//----------释放锁-------------        signal(full);       //V操作 -> (full+1)    }while(TRUE);}void consumer(){    do{        wait(full);         //P操作 -> (full-1)        wait(mutex);//------------请求锁-----------        nextc = buffer[out];        out = (out+1) % n;        signal(mutex);//----------释放锁------------        signal(empty);      //V操作 -> 又多了一个空缓存区        ...                     //消费者开始消费取出的产品nextc;        ...    }while(TRUE);}void main(){    cobegin        proceducer();        consumer();    coend}

哲学家进餐问题

哲学家们的生活方式是交替进行思考和进餐。现有五个哲学家们共用一个圆桌,有五张椅子,五个碗,五只筷子,但是一个哲学家想吃饭时,需同时拿起最近的左右筷子吃。那么该怎样协调他们吃饭的时间

1.利用记录型信号量解决

semaphore chopstick chopstick[5] = {1,1,1,1,1};do{    wait(chopstick[i]);         wait(chopstick[(i+1)%5]);       ...    //eat       ...    signal(chopstick[i]);       signal(chopstick[(i+1)%5]);         ...    //think         ...}while(TRUE);

但是,当五个哲学家同时饥饿,那么五个人同时拿起左边筷子,那么五个人就无限等待下去了。。。这就死锁了。
解决办法:
(1)至多四个人去拿左边筷子,即可保证至少有一个人可以用餐。
(2)仅当左右两只筷子均可用时,才能进餐。 (AND型信号量)√√
(3)规定奇数号的先拿起左边的,再拿右边的。偶数号则相反。√

2.利用AND型信号量机制解决

semaphore chopstick chopstick[5] = {1,1,1,1,1};do{    ...    //think    ...    Swait(chopstick[i], chopstick[(i+1)%5]);    ...    //eat    ...    Ssignal(chopstick[i], chopstick[(i+1)%5]);}while(TRUE);

读者 - 写者问题

一个数据文件或记录可被多个进程共享,其中,有些进程要求读("Reader进程"),有些进程则要求写或修改("Writer进程")。

读者优先:一旦读者正在读数据,允许多个读者同时进入读数据,只有当全部读者退出,才允许写者进入写数据

int readcount = 0;semaphore Fmutex=1;             //为保证读者与写者、写者与写者之间的互斥访问semaphore Rmutex=1, Wmutex=1;   //Rmutex为实现对readcount的互斥访问semaphore Entermutex = 1;       //void reader(){    do{        wait(Rmutex);            if(readcount==0)    wait(Fmutex);   //readcount==0时,说明读者已经访问完毕,需要释放等待队列中的一个写者进程        readcount++;            signal(Rmutex);        ...        //执行 **读** 操作        ...        wait(Rmutex);        readcount--;    //读取完毕,释放资源        if(readcount==0)    signal(Fmutex); //释放Wmutex锁        signal(Rmutex);    }while(TRUE);}void writer(){    do{        wait(Entermutex); //保证每次进入Fmutex中的写者进程只有一个             wait(Fmutex);            ...            //执行 **写** 操作            ...            signal(Fmutex);        signal(Entermutex);    }while(TRUE);}void main(){    cobegin        reader();        writer();    coend}

写者优先:一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。
这种方案虽然解决写者饥饿问题,但降低了并发程度使系统性能较差。

int readcount = 0;int writecount = 0;semaphore Fmutex=1;             //为保证读者与写者、写者与写者之间的互斥访问semaphore Rmutex=1, Wmutex=1;   //Rmutex为实现对readcount的互斥访问semaphore Entermutex = 1;semaphore Quemutex = 1;         //当Writer进程到来时,Reader进程的阻塞队列void reader(){    do{        wait(Entermutex);   //保证每次进入Quemutex中的读者进程只有一个            wait(Quemutex);                wait(Rcount);                    if(readcount == 0)  wait(Fmutex);                    readcount++;                signal(Rcount);            signal(Quemutex);        signal(Entermutex);        ...        //执行 **读** 操作        ...        wait(Rcount)        if(readecount==0)            signal(Fmutex);        signal(Rcount)    }while(TRUE);}void writer(){    do{        wait(Wmutex);            if(writecount == 0)     wait(Quemutex);            writecount++;        signal(Wmutex);        wait(Fmutex);        ...        //执行 **写** 操作        ...        signal(Fmutex);        wait(Wcount);            readcount--;            if(readcount==0)    signal(Quemutex);        signal(Wcount);    }while(TRUE);}void main(){    cobegin        reader();        writer();    coend}
0 0
原创粉丝点击