一、什么是信号量?
信号量的本质是什么?
——本质是一个数据操作锁,他本身不具有数据交换的功能,而是通过控制其他的通信资源(文件、外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责操作的互斥、同步等功能。个人理解:
信号量就是一个计数器,准确的说,是一个具有原子性的计数器。当使用资源时,计数器减一,表示外界的可用资源减少一个;当释放资源时,计数器加一,表示使用完后将资源还回去,使得外界可用资源增加一个。- 信号量是用来干什么的呢?
举例铺垫:
在创建子进程时,你是如何保证父子进程执行的先后顺序的呢?(假设让子进程先执行)
但是这样会存在一个问题,我们只能保证子进程先执行,并不能保证子进程执行完了以后就执行父进程。
于是便引入了信号量的概念,信号量可以达到这一目的,信号量是一种解决进程间同步与互斥的机制。
- 信号量是用来干什么的呢?
信号量解决的内容包括:
1.一个称为信号量的变量
2.在该信号量下等待资源的进程等待队列
3.对信号量进行的两个原子操作(P/ V操作)
二、信号量值的含义:
等待信号量(Saphore)由一个值和一个指针组成,指针指向该信号量的进程。
信号量的值表示相应资源的使用情况。
- s>0 表示可用资源的个数
- s=0: 表示没有资源可以使用,也没有进程等待该资源
- s<0 表示没有资源可以使用,有|S|个进程在等待该资源
三、信号量的工作原理:
——PV操作
- P操作:
1.如果有可用资源(s>0),则此操作的进程占用一个资源,执行一次P操作意味着请求分配一个资源——s的值减1
2.如果没有可用的资源(s=0),则此操作所在的进程被阻塞,直到系统将资源分配给该进程(进入等待队列,一直等待资源轮到该进程)
- V操作:
1.如果在该信号量的等待队列中有进程在等待该资源,则唤醒一个阻塞进程
2.如果没有进程等待它,则释放一个资源。——s的值加1
信号量操作的伪代码:
struct semaphore
{
int counter;
struct task_struct* queue;//等待队列
}
P(s)//原语——通过进程——整个内部都是原子操作
{
s.counter--; 有资源可以获取,- -获取
if(s.counter<0)
{
将调用P操作的进程置为等待状态,放入等待队列
//此时进程变成等待进程
}
}
V(s)——释放资源(先执行完P,执行V)
{
s.counter++;
if(s.counter<=0)
{
唤醒等待队列
置为就绪状态
放入就绪队列
等CPU调度算法调度到,再拿到CPU中去执行
}
}
四、信号量的操作步骤
1.创建 / 打开信号量
所需头文件:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//创建信号量,或者获得进程间已经存在的信号量
int semget(key_t key, int nsems, int semflg);
-