信号量/灯

文章介绍了信号量的概念,作为资源管理的工具,分为无名和有名两种类型,并详细阐述了它们的初始化、P操作(申请资源)、V操作(释放资源)以及如何创建、销毁。同时提到了IPC信号灯,包括ftok函数用于创建key,semget用于创建信号灯集,semop进行信号量操作。最后,给出了一个使用有名信号量实现进程间通信的测试例子。
摘要由CSDN通过智能技术生成

信号量/灯

1.概念

信号量代表某一类资源,其值标识系统中该资源的数量

信号量是一个受保护的变量,只能通过三种操作来访问

初始化

p操作(申请资源,资源-1)

v操作(释放资源,资源+1)

2.分类

在这里插入图片描述

3.无名信号量

信号量初始化

#include <semaphore.h>

int sem_init(sem_t *sem,int shared,unsigned int val)
	sem:指向要初始化的信号量对象
	shared指定为0,标识信号量只能由初始化这个信号量的进程使用,不能在进程间使用,linux不支持进程间同步
		0:线程间
		1:进程间
	val:信号量初值
	成功时返回0,失败时返回EOF

信号量P/V操作

#include <semaphore.h>

int sem_wait(sem_t *sem);	//P操作
int sem_post(sem_t *sem);	//V操作
	sem指向要操作的信号量对象
	成功时返回0,失败时返回EOF

销毁无名信号量

#include <semaphore.h>

int sem_destroy(sem_t *sem)
	sem:信号量的地址
	成功返回0失败返回-1
4.有名信号量

创建信号量

sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value)
	name:有名信号量的名字,以"/"开头
	oflag:标志位O_CREAT
	mode:八进制权限 0777 0666
	value:信号量初始化的值

信号量P/V操作

#include <semaphore.h>
int sem_wait(sem_t *sem);	//P操作
int sem_post(sem_t *sem);	//V操作
	sem指向要操作的信号量对象
	成功时返回0,失败时返回EOF

关闭信号量

#include <semaohore.h>

int sem_close(sem_t *sem);
	sem:有名信号量的指针地址
	成功返回0,失败返回-1

删除信号量

#include <semaphore.h>

int sem_unlink(const char *name)
	name:有名信号量的名字
	成功返回0,失败返回-1
5.有名信号和无名信号的区别

在这里插入图片描述

6.ipc信号灯

ftok函数创建key

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *path,int proj_id)
	path:存在且可访问的文件的路径
	proj_id:用于生成key的数字,范围1-255
	成功时返回合法的key值,失败时返回EOF

创建信号灯集

#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key,int nsems,int semflg)
	key:和信号量关联的key
	nsems:集合中包含的计数信号灯个数
	semflg:标志位 IPC_CREAT|0666 IPC_EXCL
	成功返回信号灯的id,失败返回-1

信号灯集初始化

#include <sys/ipc.h>
#include <sys/sem.h>

int semctl(int semid,int semnum,int cmd,...)
	semid:要操作的信号量
	semnum:要操作的集合中的信号灯编号
	cmd:执行的操作 SETVAL IPC_RMID
	union semun 取决于cmd

信号量pv操作

#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid,struct sembuf* sops,unsigned nsops)
	semid:要操作的信号量id
	sops:描述对信号灯操作的结构体(数组)
	nsops:要操作的信号灯的个数
	
	
struct sembuf
{
	short sem_num;
	short sem_op;
	short sem_flg;
};

semnum 信号量编号
sem_op	p操作 -1  v操作 1
sem_flg 0/IPC_NOWAIT

7.有名信号量测试

sem_w.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>

void delsemfile(int sig)
{
	sem_unlink("sem_w");
	exit(0);
}

int main()
{
	key_t key;
	int shmid;
	char* addr;
	sem_t *sem_w,*sem_r;
	int ret;

	struct sigaction act;
	act.sa_handler = delsemfile;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGINT,&act,NULL);

	key = ftok(".",10);
	if(key < 0)
	{
		perror("ftok error\n");
		return -1;
	}
	shmid = shmget(key,512,IPC_CREAT|0666);
	if(shmid < 0)
	{
		perror("shmget error\n");
		return -1;
	}
	addr = shmat(shmid,NULL,0);
	if(addr == (void *)-1)
	{
		perror("shmat error\n");
	}
	sem_w = sem_open("sem_w",O_CREAT|O_RDWR,0666,1);
	sem_r = sem_open ("sem_r",O_CREAT|O_RDWR,0666,0);

	while(1)
	{
		sem_wait(sem_w);
		printf(">>");
		scanf("%s",addr);
		sem_post(sem_r);
	}

	return 0;
}

sem_r.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>        
#include <sys/stat.h>      
#include <semaphore.h>
#include <signal.h>
#include <stdlib.h>


void delsemfile(int sig)
{
	sem_unlink("sem_r");
	exit(0);
}

int main()
{
	key_t key;
	int shmid;
	char* addr;
	sem_t *sem_w,*sem_r;
	int ret;

	struct sigaction act;
	act.sa_handler = delsemfile;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGINT,&act,NULL);

	key = ftok(".",10);
	if(key < 0)
	{
		perror("ftok error\n");
		return -1;
	}
	shmid = shmget(key,512,IPC_CREAT|0666);
	if(shmid < 0)
	{
		perror("shmget error\n");
		return -1;
	}
	addr = shmat(shmid,NULL,0);
	if(addr == (void *)-1)
	{
		perror("shmat error\n");
	}
	sem_w = sem_open("sem_w",O_CREAT|O_RDWR,0666,1);
	sem_r = sem_open ("sem_r",O_CREAT|O_RDWR,0666,0);

		sem_wait(sem_r);
		printf("%s\n",addr);
		sem_post(sem_w);

	return 0;
}

turn -1;
}
addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror(“shmat error\n”);
}
sem_w = sem_open(“sem_w”,O_CREAT|O_RDWR,0666,1);
sem_r = sem_open (“sem_r”,O_CREAT|O_RDWR,0666,0);

	sem_wait(sem_r);
	printf("%s\n",addr);
	sem_post(sem_w);

return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值