Linux编程5 信号量

1、概念

多个程序同时访问一个共享资源一般是不允许的,为了避开这个事件而引发的一系列问题,我们需要一种方式,通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待(即P(信号变量))和发送(即V(信号变量))信息操作。

2、使用说明

进程在进行v操作的时候,如果信号量中的“量”小于0,则进程睡眠阻塞。
进程在进程 p操作的时候,对应的信号量进行“量”的加操作。

3、相关函数

3.1创建信号量:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
//功能:返回与参数key关联的系统V信号量标识符,它可用于获取先前创建的信号量集的标识符
//返回:如果成功,返回值 将是信号量集标识符(非负整数),否则返回-1,同时返回errno指出错误

参数:

  • key:主键,系统根据主键建立
  • nsems:信号量集中,设置多少个具体信号量
  • mode:一组标志,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,也不会产生错误。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的信号量,如果信号量已存在,返回一个错误。
3.2打开信号量
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>


int semop(int semid, struct sembuf *sops, size_t nsops);

参数:

  • semid:信号量号
  • sops:结构体
struct sembuf{
	unsigned short sem_num; // 除非使用一组信号量,否则它为0
	short sem_op;  信号量增量,一个是-1(P等待),一个是+1(V发送信号)
	short sem_flg; 属性,通常为SEM_UNDO
	 };
  • nsops: 一般是1,操作一次

返回值:

  • 0成功,-1失败
3.3 信号量操作
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/sem.h>
 int semctl(int semid, int semnum, int cmd, ...);
 //返回:0成功,-1失败

参数:

  • semid: 信号量号
  • semnum:信号量集下标
  • cmd:IPC_IPC_RMID删除
  • 可变参数部分根据具体其它cmd来选择

可能的cmd是
在这里插入图片描述

4、完整示例

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>

int main(void)
{
	//					键 信号量个数  IPC_CREAT没有则创建
	int semid = semget(1234, 1, 0664 | IPC_CREAT);//创建信号量
	if(semid < 0){
		perror("信号量创建失败:");
		exit(1);
	}

	struct sembuf sem;
	sem.sem_num = 0;//当前信号量
	sem.sem_flg = SEM_UNDO;//默认操作,即没有量则阻塞

	sem.sem_op = -3;
	while(1){
		//做V操作,获取信号量
		semop(semid, &sem, 1);
		printf("helloworld\n");
	}

	//删除 semid  当前  删除   值
	semctl(semid, 0, IPC_RMID, 0);

	return 0;
}
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<sys/ipc.h>

int main(void)
{
	//
	int semid=semget(1234,1,0);
	if(semid<0)
	{
		perror("信号量创建失败!");
		exit(1);
	}

	struct sembuf sem;
	sem.sem_num=0;
	sem.sem_flg=SEM_UNDO;
	sem.sem_op=1;

	while(1)
	{
		getchar();
		semop(semid,&sem,1);
		//printf("helloworld\n");
	}

	semctl(semid,0,IPC_RMID,0);

	

	return 0;
}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值