系统编程之进程间的 信号量 通信(4)
系列文章目录
目录
前言
这篇文章将讲述另一种进程间通信的机制——信号量。注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物。
一、信号量
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
作用:协调多个进程在通信的时候,对于共享资源(临界区资源)的访问。
1 信号量的工作原理
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.
举个例子,就是两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区,使sv减1。而第二个进程将被阻止进入临界区,因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。
2 信号量相关命令
ipcs -s // 查看信号量
ipcrm -s 信号量的ID // 删除信号量
3 相关的接口函数
3.1 申请信号量(信号灯)
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg)
参数1:key(唯一非零):不相关的进程可以通过它访问一个信号量
参数2:nsems:你打算申请多少个信号量
参数3:sem_flags:代表一组标志,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作
返回值:成功返回一个相应信号标识符(非零)
失败返回-1
semget(key, 2,IPC_CREAT|IPC_EXCL|0777);
3.2 操作信号量
PV操作:
p操作:对信号量的值做减法运算
v操作:对信号量的值做加法运算
tips: 可以把semop函数做二次封装
int p操作(int 减少多少,int 哪个信号量)
{
semop(int semid, struct sembuf *sops, size_t nsops);
}
int v操作(int 减少多少,int 哪个信号量)
{
semop(int semid, struct sembuf *sops, size_t nsops);
}
int semop(int semid, struct sembuf *sops, size_t nsops);
返回值:成功0 失败-1
参数1:sops :结构体指针
struct sembuf
{
unsigned short sem_num; //信号量的序号,序号从0开始
short sem_op; //你想对信号量进行p操作还是v操作
short sem_flg; //SEM_UNDO,pv操作改变信号量的值,下次重新运 行,信号量恢复成原始值
}
参数2:nsops:struct sembuf的个数,一般设置为1
3.3 设置信号量的值,获取值,删除信号量
int semctl(int semid, int semnum, int cmd, ...);
参数:semnum:信号量的序号
cmd:IPC_RMID //删除信号量
GETVAL //我想获取信号量的值
SETVAL //我想设置信号量的值
semctl(semid, 0, IPC_RMID ); //我要删除第一个信号量
semctl(semid, 1, IPC_RMID ); //我要删除第二个信号量 int value=semctl(semid, 0, GETVAL); //我要获取第一个信号量的值,返回值就是信号量的值 semctl(semid, 0, SETVAL,1); //我要把第一个信号量的值设置为1
4 信号量的特点
- 信号量的值不能是负数,信号量值为0,你还要进行p操作,会阻塞当前进程,v操作做加法,不会阻塞进程。
- 信号量表示进程拥有的资源的数量,比如:值是5,进程拥有5个资源 p操作剥夺我的资源 v操作增加资源。
总结
以上就是本文要讲的内容,本文仅仅简单介绍了信号量的原理和使用方法。