操作系统原理教程:信号量和PV操作

信号量S(Semaphore)是一个结构体变量,它有两个数据项:一个是值域,另一个是指针域。值域用于保存信号量的值,指针域用于保存指向等待该信号量队列的指针。

# 信号量定义

struct semaphore
{
    int value;
    struct PCB* queue;
};

信号量是由操作系统来维护的,用户进程只能通过初始化和两个标准原语,即P原语和V原语来对它进行访问。所谓原语,其实就是一个函数,它通常由若干条语句组成,用来实现某个特定的操作。与普通函数的区别在于:它是由操作系统提供的,而且在执行过程中不会被中断所打断。原语是操作系统内核的一个组成部分,它必须在管态下执行。

# P操作

void P(semaphore S)
{
    S.value--;
    if(S.value < 0)
        block(S.queue);     // 将进程阻塞,并将其插入等待队列
}
# V操作

void V(semaphore S)
{
    S.value++;
    if(S.value<=0)
        wakeup(S.queue);    // 唤醒阻塞进程,将其从等待队列取出,插入就绪队列
}

信号量的物理意义:

  • 在信号量机制中,信号量的初值S.value标识系统中某种资源的数目,因而又称为资源信号量。

  • P操作意味着进程请求一个资源,因此描述为S.value=S.value-1;当S.value<0时,表示资源已经分配完毕,因而进程所申请的资源不能够满足,进程无法继续执行,所以进程执行block(S.queue)自我阻塞,放弃处理机,并插入到等待该信号量的等待队列。

  • V操作意味着进程释放一个资源,因此描述为S.value=S.value+1;当S.value<0时,表示在该信号量的等待队列中有等待该资源的进程被阻塞,故应调用wakeup(S.queue)原语将等待队列中的一个进程唤醒。

  • S.value<0时,|S.value|表示等待队列的进程数。

用信号量解决互斥问题

如果信号量的初值为1,表示仅允许一个进程访问临界区,此时的信号量转换为互斥信号量。P操作和V操作分别置于进入区和退出区便可实现多个进程互斥进入临界区。

# P1、P2两个进程共享变量count

设P1和P2共享信号量为mutex,且mutex的初值为1void P1()                                       void P2()
{                                               {
    ...                                             ...
    P(mutex);                                       P(mutex);
    N = count;                                      M = count;
    N = N + 100;                                    M = M + 200;
    count = N;                                      count = M;
    V(mutex);                                       V(mutex);              
    ...                                             ...
}                                                }

void main()
{
    semaphore mutex = 1;
    cobegin
        P1();
        P2();
    coend
}     
用信号量解决同步问题

利用信号量可以实现进程之间的同步,即可以控制进程执行的先后次序。根据信号量的初值,在某个进程的程序段前加P操作,在另一个的程序段后加V操作即可。

# 有两个进程P1和P2,进程P1中有一个语句S1,进程P2中有一个语句S2。
# 要求必须在P1执行完S1语句后,P2才能执行S2。

设P1和P2共享信号量S,且S的初值为0void P1()                                         void P2()
{                                                 {
    ...                                               ...
    S1;                                               P(S);
    V(S);                                             S2;
    ...                                               ...
}                                                  }

void main()
{
    semaphore S = 0;
    cobegin
        P1();
        P2();
    coend
}
用信号量同时解决同步与互斥问题

利用信号量机制可以在实现进程同步的同时也实现进程互斥,即在控制进程执行的先后次序的同时,也实现了进程互斥使用共享变量或共享资源。

# 供者进程L1将读卡机中的数据放入缓冲区,用者进程L2从缓冲区中读取数据送打印机。

设置两个信号量。S1:表示缓冲区是否为空(0表示不空,1表示空)、S2:表示缓冲区是否满(0表示不满,1表示满)
置初值:S1=1,S2=0

void L1()                                           void L2()        
{                                                   {
    do{                                                 do{
        ...                                                 ...
        P(S1);                                              P(S2);
        启动读卡机;                                          从缓冲区取出信息;
        读入数据至缓冲区;                                     V(S1);
        收到输入结束中断;                                     加工并且存盘;
        V(S2);                                          }while(true);
    }while(true);                                   }   
}

void main()
{
    semaphore S1=1, S2=0;
    cobegin
        L1();
        L2();
    coend
}

(最近更新:2019年09月18日)

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值