信号灯也叫信号量,是不同进程间或一个给定进程内部不同线程间同步的机制。
信号灯集为信号量的集合,实现同步、互斥机制,配合共享内存使用,解决资源竞争问题。
函数: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值ftokkey_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的值初始化为1semctl(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;控制的信号灯个数为1if(strcmp(buf,"exit") == 0)break;}//6、撤销映射shmdt(buf);//7、删除共享内存IPC对象shmctl(shmid,IPC_RMID,NULL);//8、删除信号灯集IPC对象semctl(semid,0,IPC_RMID,NULL); //删除信号灯0semctl(semid,1,IPC_RMID,NULL); //删除信号灯1return 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值ftokkey_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的值初始化为1semctl(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->Vstruct sembuf sem_1 = {1,-1,0}; //信号灯1->Pwhile(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); //删除信号灯0semctl(semid,1,IPC_RMID,NULL); //删除信号灯1return 0;
}
结果