《计算机操作系统》——信号量机制以及实现进程互斥、同步、前驱关系

信号量机制

  用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。
  信号量其实就是一个变量(可以是一个整数,也可以是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量,比如:系统中只有一台打印机,就可以设置一个初值为1的信号量。

整形信号量

  • 整形信号量与一般整形量不同,除初始化之外,仅能通过两个标准的原子操作wait(S)和signal(S)来访问,这两个操作也被称为P、V操作,用于实现系统资源的“申请”和“释放”。
  • “检查”和“上锁”一气呵成,避免了并发、异步导致的问题。
    • 不满足让权等待原则,会发生“忙等”。
      请添加图片描述

记录型信号量

  • 用S.value的初值表示系统中某种资源的数目。
  • 对信号量S的一次P操作意味着进程请求一个单位的该类资源,因此S.value–,表示资源数减1,当S.value<0时表示该类资源已分配完毕,因此进程应调用block原语进行自我阻塞,主动放弃处理机,并插入该类资源的等待队列S.L中。
  • 对信号量S的一次V操作意味着进程释放一个单位的该类资源,因此需要执行S.value++,表示该资源数加1,若加1后仍是S.value≤0,表示依然有进程在等待该类资源,因此应调用wakeup原语幻想等待队列中的第一个进程。
  • 遵循了“让权等待”原则,不会出现“忙等”现象。
    请添加图片描述

AND型信号量

  (王道的课程中信号量机制只说了上述两种,这里的AND型信号量来自汤子瀛的计算机操作系统书本)

  • ADN型信号量主要针对的是一个进程需要获取两个或更多的共享资源执行任务时的问题。
  • 基本思想:对若干个临界资源的分配采取原子操作的方式:要么把它所请求的资源全部分配到进程,要么一个也不分配。为此,在wait中加入了一个“AND”条件,故称为AND同步,或称为同时wait操作,即Swait(Simultaneous wait)定义如下:
Swait(S1,S2,....,Sn)
{
    while(true)
    {
        if(Si>=1 && ... && Sn>=1){
            for(i=1;i<=n;i++)Si--;
            break;
        }
        else{
        //将进程放入第一个Si<1对应的i等待队列
        //并且设置S1~Sn的资源数量为Swait()操作前的数量
        }
    }
}

Ssignal(S1,S2,...,Sn){
    while(true){
        for(i=1;i<=n;i++){
            Si++;
            //将所有Si等待队列内的进程放入就绪队列
        }
    }
}

信号量集

  (王道的课程中信号量机制只说了上述两种,这里的信号量集来自汤子瀛的计算机操作系统书本)

  • 信号量集主要针对的是执行进程时一次需要N个单位的某类临界资源的问题
  • 对AND型信号量机制加以扩充,对进程所申请的所有资源以及每类资源不同的资源量需求,在一次P、V原语操作中完成申请或释放。
  • 进程对信号量Si的测试值不再是1,而是该资源的分配下限ti,即要求Si>=ti。一旦允许分配,进程对该资源的需求值为di,即表示资源占用量,进行Si:=Si-di的操作,对应的Swait和Ssignal格式为:
Swait(S1,t1,d1,...,Sn,tn,dn);
Ssignal(S1,d1,...,Sn,dn);
  • Swait(S,d,d):此时信号量集中只有一个信号量S,但允许它每次申请d个资源,当现有资源数量少于d时,不予分配。
  • Swait(S,1,1):此时信号量集已蜕化为一般的记录型信号量(S>1时)或互斥信号量(S=1)。
  • Swait(S,1,0):当S>=1时,允许多个进程进入某特定区;当S变为0后,将阻止任何进程进入特定区,相当于一个可控开关。

整形信号量与记录型信号量

请添加图片描述

信号量的应用

请添加图片描述

信号量机制实现进程互斥

  • 设置mutex为互斥信号量,初值为1,取值范围为(-1,0,1)。
    当mutex = 1 时,表示两个进程皆未进入互斥的临界区
    当mutex = 0 时,表示有一个进程进入临界区运行,另一个必须等待,挂入阻塞队列
    当mutex = -1 时,表示有一个进程正在临界区运行,另外一个进程因等待而阻塞在信号量队列中,需要被当前已在临界区运行的进程退出时唤醒。
  • P、V操作必须成对出现,缺少P(mutex)将会导致系统混乱,不能保证对临界资源的访问,缺少V(mutex)将会使临界资源永远不被释放,从而使因等待该资源而阻塞的进程永远不能被唤醒。
/*信号量机制实现互斥*/
semaphore mutex = 1;  //初始化信号量

P1(){
   while(1){
       wait(mutex);    //使用临界资源前需要加锁
       //临界区;
       signal(mutex);  //使用临界资源后需要解锁
       //剩余区;
   }
}

P2(){
   while(1){
       wait(mutex);
       //临界区;
       signal(mutex);
       //剩余区;
   }
}

信号量机制实现进程同步

  • 设置同步信号量S,初始为0
  • 在“前操作”之后执行V(S)
  • 在“后操作”之前执行P(S)
    请添加图片描述

信号量机制实现前驱关系

  每一对前驱关系都是一个进程同步问题

  • 要为每一对前驱关系各设置一个同步变量
  • 在“前操作”之后对相应的同步变量执行V操作
  • 在“后操作”之前对相应的同步变量执行P操作请添加图片描述

总结

考察多资源问题即为前面写到的AND型信号量信号量集的相关问题
请添加图片描述

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux中,可以使用信号和PV原语操作机制实现进程同步互斥。 1. 同步机制:可以使用信号实现进程同步信号是一种计数器,它用来控制多个进程对共享资源的访问。在Linux中,信号由semget、semop和semctl三个系统调用来完成。 2. 互斥机制:可以使用PV原语操作机制实现进程互斥。PV原语操作机制可以实现原子操作,保证多个进程对共享资源的访问是互斥的。在Linux中,PV原语操作机制由semaphore.h头文件中的sem_init、sem_wait和sem_post三个函数来实现。 下面是一个简单的示例代码: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <semaphore.h> sem_t sem; // 定义信号 void *thread_func(void *arg) { sem_wait(&sem); // 等待信号 printf("Thread %d is running\n", *(int *)arg); sem_post(&sem); // 发送信号 return NULL; } int main() { sem_init(&sem, 0, 1); // 初始化信号 pthread_t tid[5]; int i; for (i = 0; i < 5; i++) { int *arg = malloc(sizeof(int)); *arg = i; pthread_create(&tid[i], NULL, thread_func, arg); // 创建线程 } for (i = 0; i < 5; i++) { pthread_join(tid[i], NULL); // 等待线程结束 } sem_destroy(&sem); // 销毁信号 return 0; } ``` 在上面的示例代码中,我们使用了sem_wait和sem_post函数来实现线程的同步。在每个线程中,我们使用sem_wait函数等待信号,当信号的值为1时,线程可以继续执行。在线程执行完后,我们使用sem_post函数发送信号,将信号的值加1,以便其他线程可以继续执行。同时,我们使用sem_init函数初始化信号,使用sem_destroy函数销毁信号

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值