信号灯也叫信号量,是不同进程间或一个给定进程内部不同线程间同步的机制。
信号灯集为信号量的集合,实现同步、互斥机制,配合共享内存使用,解决资源竞争问题。
函数:semget、semctl、semop
实现流程:
1、创建信号灯集的IPC对象 semget
2、信号灯集初始化 semctl
3、创建共享内存IPC对象 shmget
4、内存映射 shmat
5、PV操作 semop
6、撤销映射 shmdt
7、删除共享内存IPC对象 shmctl
8、删除信号灯集IPC对象 semctl
write.c
/*===============================================
* 文件名称:write.c
* 创 建 者:cxy
* 创建日期:2024年02月08日
* 描 述:
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <string.h>
/*
struct sembuf{ //保存信号灯信息的结构体
unsigned short sem_num; //控制的信号灯编号
short sem_op; //-1为P操作,1为V操作
short sem_flg; //0为默认操作方式
};
*/
int main(int argc, char *argv[])
{
//1、创建信号灯集IPC对象semget
//1.1、获取key值ftok
key_t key = ftok("/home",44); //非0数
//1.2、创建信号灯集IPC对象
//获取信号灯集id号
int semid = semget(key,2,IPC_CREAT|0664); //信号灯集中信号灯的个数为2
//2、信号灯集初始化
semctl(semid,0,SETVAL,1); //将信号灯0的值初始化为1
semctl(semid,1,SETVAL,0); //将信号灯1的值初始化为0
//3、创建共享内存IPC对象
key_t shmkey = ftok("/home",45);
int shmid = shmget(shmkey,1024,IPC_CREAT|0664); //共享内存带小为1024字节
//4、内存映射
char *buf = shmat(shmid,NULL,0); //NULL为地址由操作系统分配,0为可读可写
//5、PV操作
struct sembuf sem_0 = {0,-1,0}; //信号灯0做P操作(P-V+)
struct sembuf sem_1 = {1,1,0}; //信号灯1做V操作(P-V+)
while(1)
{
semop(semid,&sem_0,1); //值:1->0;控制的信号灯个数为1
scanf("%s",buf);
semop(semid,&sem_1,1); //值:0->1;控制的信号灯个数为1
if(strcmp(buf,"exit") == 0)
break;
}
//6、撤销映射
shmdt(buf);
//7、删除共享内存IPC对象
shmctl(shmid,IPC_RMID,NULL);
//8、删除信号灯集IPC对象
semctl(semid,0,IPC_RMID,NULL); //删除信号灯0
semctl(semid,1,IPC_RMID,NULL); //删除信号灯1
return 0;
}
read.c
/*===============================================
* 文件名称:read.c
* 创 建 者:cxy
* 创建日期:2024年02月08日
* 描 述:
================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <string.h>
/*
struct sembuf{ //保存信号灯信息的结构体
unsigned short sem_num; //控制的信号灯编号
short sem_op; //-1为P操作,1为V操作
short sem_flg; //0为默认操作方式
};
*/
int main(int argc, char *argv[])
{
//1、创建信号灯集IPC对象semget
//1.1、获取key值ftok
key_t key = ftok("/home",44); //非0数
//1.2、创建信号灯集IPC对象
//获取信号灯集id号
int semid = semget(key,2,IPC_CREAT|0664); //信号灯集中信号灯的个数为2
//2、信号灯集初始化
semctl(semid,0,SETVAL,1); //将信号灯0的值初始化为1
semctl(semid,1,SETVAL,0); //将信号灯1的值初始化为0
//3、创建共享内存IPC对象
key_t shmkey = ftok("/home",45);
int shmid = shmget(shmkey,1024,IPC_CREAT|0664); //共享内存带小为1024字节
//4、内存映射
char *buf = shmat(shmid,NULL,0); //NULL为地址由操作系统分配,0为可读可写
//5、PV操作
struct sembuf sem_0 = {0,1,0}; //信号灯0->V
struct sembuf sem_1 = {1,-1,0}; //信号灯1->P
while(1)
{
semop(semid,&sem_1,1); //由于sem_1为0,所以阻塞等待,写端完成一次while后,信号灯1已由0->1再P-,信号灯0已由1->0再V+
printf("%s\n",buf);
semop(semid,&sem_0,1);
if(strcmp(buf,"exit") == 0)
break;
}
//6、撤销映射
shmdt(buf);
//7、删除共享内存IPC对象
shmctl(shmid,IPC_RMID,NULL);
//8、删除信号灯集IPC对象
semctl(semid,0,IPC_RMID,NULL); //删除信号灯0
semctl(semid,1,IPC_RMID,NULL); //删除信号灯1
return 0;
}
结果