进程间通信(四)——信号量

系列文章目录

进程间通信(零)——说明
进程间通信(一)——管道
进程间通信(二)——信号
进程间通信(三)——共享内存
进程间通信(四)——信号量



一、信号量的概念

1、基本概念

信号量(灯),是替代互斥锁的另一种概念,用于解决多线程间同步和互斥,特别是访问临界资源时的同步访问。
NOTE:信号量本身和信号并没有什么特殊的交集

2、调用逻辑

信号量很像一个“开关”,n表示可用资源的数量,一共有3种情况:

  • n>0 资源可用,数量为n
  • n=0 资源被占用,当前可用资源数量为0
  • n<0 资源被占用,当前可用资源数量为-n
    信号量的操作有"P"、"V"操作
  • P操作 减法操作,资源数量value会-1
  • V操作 加法操作,资源数量value会+1

二、共享内存调用

API

函数说明
sem_init()初始化信号量
sem_wait()加锁
sem_post()解锁
sem_destroy()销毁信号量

1.初始化信号量

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
参数
	key		键值,和共享内存的方式一样
	nsems	信号量的数量,设置为1
	semflg	位掩码,IPC_CTEAT、IPC_EXCL等
返回值:
	成功 —— semid		失败 —— -1

2.PV操作

2.1 结构体

struct sembuf
{
     unsigned short sem_num;  /* semaphore number*/
     short          sem_op;   /* semaphore operation */
     short          sem_flg;  /* operation flags */
}
说明
	sem_num		信号灯下标
	sem_op		PV操作标志
					如果是正数,就是V操作
					如果是负数,就是P操作
	Sem_flg		是否阻塞	
					0  			代表阻塞		
					IPC_NOWAIT  不阻塞

2.2 API

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, size_t nsops,
                      const struct timespec *timeout);
参数:	
	semid		信号集ID号	(semget的返回值)
	sops		数组
	nsops		数组的大小(个数)
	timeout		时间参数,为NULL时,semtimedop()semop()没有区别。
返回值:
	成功 —— 0		错误 —— 1

3.控制信号量

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
参数
	semId		信号量集ID号
	senum		某个信号灯的下标
	cmd			命令
					SETVAL		设置value
					GETVAL		得到value
					IPC_RMID	删除信号灯集(整个)

3.1 结构体


union semun 
{
	int              val;    /* Value for SETVAL */
	struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
	unsigned short  *array;  /* Array for GETALL, SETALL */
	struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux-specific) */
};
struct semid_ds 
{
	struct ipc_perm sem_perm;  /* Ownership and permissions */
	time_t          sem_otime; /* Last semop time */
	time_t          sem_ctime; /* Last change time */
	unsigned long   sem_nsems; /* No. of semaphores in set */
};
struct ipc_perm 
{
	key_t          __key; /* Key supplied to semget(2) */
	uid_t          uid;   /* Effective UID of owner */
	gid_t          gid;   /* Effective GID of owner */
	uid_t          cuid;  /* Effective UID of creator */
	gid_t          cgid;  /* Effective GID of creator */
	unsigned short mode;  /* Permissions */
	unsigned short __seq; /* Sequence number */
};

3.2 设置信号量

当cmd的值是 SETVAL时
union semun us; 
us.val = 5;
semctl(semid,0,SETVAL,us,NULL);

3.3 获取信号量信息

因为每次操作资源时,如果某个资源经过V操作,已经是6,如果只执行了2此P操作6-2=4,即使进/线程完全结束,资源仍然是锁定状态,我们最好先确认value的值。

当cmd的值是 GETVAL时   
value = semctl(semid,0,GETVAL,NULL);

3.4 删除信号量

当cmd的值是 IPC_RMID时   
semctl(semid,0,IPC_RMID,NULL);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值