第2章 进程管理

进程概念的引入

从静态角度看,进程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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值