POXIS信号量

一、有名信号量

1、POSIX有名信号量
有名信号量创建成功之后会在系统中的一个特殊的虚拟文件系统 /dev/shm,不同的进程间约好同一名,即可通过这种有名信号量来相互协调。还有有名信号量和system-V的信号量一样,进程退出不会自动消失,需要人手删除并释放资源

使用步骤:
1.1 使用sem_open()创建或者打开一个有名信号量
1.2 使用sem_wait()和sem_post()来分别进行p操作和v操作
1.3 使用sem_close()关闭信号量
1.4 使用sem_unlink()删除信号量,释放系统资源

2、API函数原型
在这里插入图片描述
在这里插入图片描述
不想system-V的信号量可以申请或者释放超过1个资源,对于POSIX信号量而言,每次只能申请或释放资源数1,当调用sem_wait()时,资源为0会阻塞,如果不想阻塞可以使用sem_trywait()l来代替

在这里插入图片描述
3.有名信号量例子
两个进程间通过使用有名信号量访问功效内存通信,semname1.c往共享内存写数据,semname2.c读取功效内存数据

semname1.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>

#define SHMSIZE 1024 	//共享内存大小
#define SEMNAME "test"	//有名信号量名字


int main(int argc, void *argv[])
{
	key_t key = ftok("./", 100);	//生成键值
	int id = shmget(key, SHMSIZE, IPC_CREAT|0666);	//获取功效内存id
	char *shmaddr = shmat(id, NULL, 0);				//申请共享内存资源
	
	sem_t *s;
	s = sem_open(SEMNAME, O_CREAT, 0777, 0);		//创建有名信号量
	
	while(1)
	{
		fgets(shmaddr, SHMSIZE, stdin);
		sem_post(s);								//释放有名信号量,V操作
		
		if(!strncmp(shmaddr, "quit", 4) )			//输入“quit”退出while
			break;	
	}
	
	sem_close(s);									//关闭有名信号量
	sem_unlink(SEMNAME);							//删除有名信号量
	exit(0);
}

semname2.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>

#define SHMSIZE 1024 	//共享内存大小
#define SEMNAME "test"	//有名信号量名字


int main(int argc, void *argv[])
{
	key_t key = ftok("./", 100);	//生成键值
	int id = shmget(key, SHMSIZE, IPC_CREAT|0666);	//获取功效内存id
	char *shmaddr = shmat(id, NULL, 0);				//申请共享内存资源
	
	sem_t *s;
	s = sem_open(SEMNAME, O_CREAT, 0777, 0);		//创建或打开有名信号量
	
	while(1)
	{
		sem_wait(s);								//申请有名信号量,P操作
			
		if(!strncmp(shmaddr, "quit", 4) )			//输入“quit”退出while
			break;	
			
		printf("receive:%s\n", shmaddr);
	}
	
	sem_close(s);									//关闭有名信号量
	sem_unlink(SEMNAME);							//删除有名信号量
	exit(0);
}

二、无名信号量(匿名信号量)

1、POSIX无名信号量
如果我们要解决进程内部的同步互斥,不需要使用有名信号量,因为同一进程里的线程内存是共享,基于内存的(不在任何文件系统内部)无名信号量来达到目的。
有关函数如下所示:

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_post(sem_t *sem);		//释放信号量
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_destroy(sem_t *sem);

使用无名信号量步骤:
1.1在线程能访问到的区域定义这种变量(如全局变量),类型sem_t
1.2任何线程使用之前都要用sem_init()初始化
1.3 使用sem_wait()、sem_tywait()和sem_post()来分别进行P/V操作
1.4 不在需要时,使用sem_destroy()来销毁

无名信号量API函数原型
sem_wait()he sem_post()跟POSIX有名信号量一样。

在这里插入图片描述

2.无名信号量例子

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <pthread.h>

#define SIZE 1024 	//内存大小

char buf[SIZE] = {0};
sem_t space, data;

void *RoutineRead(void *arg)
{
	char *bufv = (char *)arg;
	
	while(1)
	{
		sem_wait(&data);						//申请无名信号量data资源,P操作
		if(!strncmp(bufv, "quit", 4) )			//输入“quit”退出while
			break;	

		printf("len:%d receive:%s\n", strlen(bufv), bufv);
		
		sem_post(&space);						//释放无名信号量space资源,V操作					
	}	
}

int main(int argc, void *argv[])
{
	sem_init(&space, 0, 1);						//初始化无名信号量,参数2:0代表线程,非0代表非线性,参数3:初始化值为1
	sem_init(&data,  0, 0);	
		
	pthread_t tid1;	
	pthread_create(&tid1, NULL, RoutineRead, (void *)buf);
	
	while(1)
	{
		sem_wait(&space);						//申请无名信号量space资源,P操作
		memset(buf, 0, sizeof(buf));
		fgets(buf, SIZE, stdin);
		sem_post(&data);						//释放无名信号量data资源,V操作
		
		if(!strncmp(buf, "quit", 4) )			//输入“quit”退出while
			break;	
	}
	pthread_join(tid1, NULL);					//阻塞等待子线程tid1退出
	sem_destroy(&data);							//销毁无名信号量
	sem_destroy(&space);
	exit(0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值