linux c 进程间使用信号量互斥的简单样例

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/sem.h>

/*
 * brief : 创建信号量
 * param : 
 *	sem_id : 信号量键值,  一个唯一的非零整数, 不同的进程可以通过它访问同一个信号量。
 *	num_sems : 信号量数目, 它几乎总是取值为1.
 *	sem_flags:	它低端的9个比特是该信号量的权限,其作用类似于文件的访问权限。
 *				它还可以和值IPC_CREAT做按位或操作,来创建新的信号量。
 *				可以联合使用标志IPC_CREAT和IPC_EXCL, 确保创建出的是一个新的、唯一的信号量。
 *				如果该信号量已存在,它将返回一个错误。
 * ret :
 *		-1 失败
 *		>0 文件描述符
 */ 
/*semget(sem_id, sem_ops, num_sem_ops) ;*/

/*
 * brief : 用于改变信号量的值。
 * param : 
 *	sem_id : 信号量的文件描述符
 *	sem_ops : 操作数据结构.
 *			struct sembuf {
 *				short sem_num ;		信号量编号,一般为 0 
 *				short sem_op ;		一次操作要改变的数值,-1 P操作 , 1 V操作. 
 *									如果其值为正数,该值会加到现有的信号内含值中。
 *									通常用于释放所控资源的使用权;
 *									如果sem_op的值为负数,而其绝对值又大于信号的现值,
 *									操作将会阻塞,直到信号值大于或等于sem_op的绝对值。
 *
 *				short sem_flag ;	通常被设置成SEM_UNDO, 
 *									它将使操作系统跟踪当前进程对这个信号量的修改情况,
 *									如果这个进程在没有释放信号量的情况下终止,
 *									OS将自动释放该进程持有的信号量。
 *			}
 *	num_sem_ops : 表示结构数组sem_ops的个数
 * ret :
 *		-1 失败
 *		0 成功
 */ 
/*semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops) ;*/

/*
 * brief : 直接控制信号量信息
 * param : 
 *	sem_id : 信号量的文件描述符 
 *	sem_num : 信号理编号,一般取值为0
 *	command : 将要采取的动作
 *		SETVAL: 用来把信号量初始化为一个已知的值
 *
 * ret :
 *		-1 失败
 *		0 成功
 */ 
/*semctl(int sem_id, int sem_num, int command, ...) ;*/

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};

int initSem(int semId){
	union semun semUnit ;
	semUnit.val = 0 ;
	if (semctl(semId, 0, SETVAL, semUnit) < 0) {
		printf("fail to init sem\n");
		return -1 ;
	}
	return 0 ;
}

int semP(int semId){
	struct sembuf op ;
	op.sem_num = 0 ;
	op.sem_op = -1 ;
	op.sem_flg = SEM_UNDO ;

	if (semop(semId, &op, 1) < 0) {
		printf("p fail\n");
		return -1 ;
	}
	return 0 ;
}

int semV(int semId){
	struct sembuf op ;
	op.sem_num = 0 ;
	op.sem_op = 1 ;
	op.sem_flg = SEM_UNDO ;

	if (semop(semId, &op, 1) < 0) {
		printf("v fail\n");
		return -1 ;
	}
	return 0 ;
}

int delSem(int semId){
	union semun semUnit ;
	if(semctl(semId, 0, IPC_RMID, semUnit) < 0){
		printf("fail to delete\n");
		return -1 ;
	}
	return 0 ;
}

int main(int argc, char** argv) {

	int semId = semget((key_t)1234, 1, 0666) ;
	if(semId < 0){
		printf("get sem fail \n");
		semId = semget((key_t)1234, 1, 0666 | IPC_CREAT) ;
		initSem(semId) ;
	}
	/*delSem(semId) ;*/

	if(argc > 1){
		while(1){
			printf("before v semId\n");
			semV(semId) ;
			printf("after v semId\n");
			sleep(2);
		}
	}else{
		while(1){
			printf("before p semId\n");
			semP(semId) ;
			printf("after p semId\n");
			sleep(2);
		}
	}

	return 0;
}

编译: gcc sem.c

运行消费者:./a.out

运行生产者: ./a.out  1

命令行中查看和删除信号量的命令

ipcs -s
ipcrm -s [ID]

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值