Linux 信号量

信号量可以用于线程间同步和进程间通信。常见的操作PV。
支持进程和线程

int semget(key_t key, int nsems, int semflg);
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
                      struct timespec *timeout);
int semctl(int semid, int semnum, int cmd, ...);                      

仅仅支持线程间同步:由于这部分相对简单,暂时不做讲解

int sem_init(sem_t *sem, int pshared, unsigned int value);
//V
int sem_post(sem_t *sem);
//P
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

int sem_getvalue(sem_t *sem, int *sval);
int sem_destroy(sem_t *sem);

创建信号量:

int semget(key_t key, int nsems, int semflg);
@param key 一个整数值,不同的进程可以通过它访问同一个信号量,也可以通过ftok获取。特例,IPC_PRIVATE表示私有,仅限当前进程访问。
@param nsems:需要信号量的数量,几乎总是为1
@param semflag:与open标志类似,IPC_CREAT,IPC_EXCL

//ftok的路径一定要存在,所以一般设置为当前目录
key_t k = ftok(".",1);
g_semid = semget(k,1,0666|IPC_CREAT);

PV操作

int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);
@param semid:信号量的id
@param sembuf:进行pv操作的变量
@param nsops:sembuf的数量
其中涉及到sembuf,结构如下

strict{
 	unsigned short sem_num; //信号量编号,从0开始,除非是一组信号量,否则一般取值0
    short          sem_op; //信号量改变的数值,P -1,V +1
    short          sem_flg;//SEM_UNDO,IPC_NOWAIT
    //SEM_UNDO进程终止之后自动释放该信号量,如果没有特殊要求应该设置SEM_UNDO
}
 int sem_p()
{
	struct sembuf sbuf = {0};
	sbuf.sem_num = 0;
	sbuf.sem_op = -1;
	//sbuf.sem_flg = SEM_UNDO|IPC_NOWAIT;
	sbuf.sem_flg = SEM_UNDO;
	return semop(g_semid,&sbuf,1);
}

int sem_v()
{
	struct sembuf sbuf = {0};
	sbuf.sem_num = 0;
   	sbuf.sem_op = 1;
   	sbuf.sem_flg = SEM_UNDO;
   	return semop(g_semid,&sbuf,1);
}

信号量设置和删除

int semctl(int semid, int semnum, int cmd, ...);
@param semid:信号量id
@param semnum:信号量编号,从0开始。除非是一组信号量,否则一般取值0
后面参数根据cmd值不同,而不同
SETVAL:用于设定信号量的值,通过union semnu中的val设置(可以多次设置,但是往往用于初始化)
IPC_RMID:删除一个无法使用的信号量标志
关于更多标志,可以参考手册。或者https://blog.csdn.net/shenwansangz/article/details/44259349

//系统并未定义该联合体,所以需要自己定义
union semun{
	int val;
   	struct semid_ds *buf;
   	unsigned short *array;
   	struct seminfo *_buf;
   	};
   	
int sem_setval(int val)                                                                                                                                                              
{  
   	union semun sun;
   	sun.val = val;
   	return semctl(g_semid,0,SETVAL,sun);
}  

int sem_rm(int sem_id)
{
	union semun sun;
   	return semctl(sem_id,0,IPC_RMID,sun);
}

注意事项:

  • 信号量属于系统资源,使用完成之后一定要删除信号量,否则会一直存在系统中(和进程是否退出无关)。
  • IPC_RMID删除信号量的时候是真正的删除(不存在引用计数的说法),所以删除的时候一定要确保不再使用在删除。
  • 如果使用了SETVAL之后,那么以后初次获取该信号量之后将自动拥有该设置的初始值,除非删除之后重新创建或者重新SETVAL。

在这里插入图片描述

IPC_PRIVATE运行两次结果:说明进程每次运行的时候,获取的semid是不一样的。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值