进程间通信(5):信号灯集

信号灯也叫信号量,是不同进程间或一个给定进程内部不同线程间同步的机制。

信号灯集为信号量的集合,实现同步、互斥机制,配合共享内存使用,解决资源竞争问题。

函数: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 
#include 
#include 
#include 
#include 
#include 
/*
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 
#include 
#include 
#include 
#include 
#include 
/*
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;
} 

结果

进程间通信(5):信号灯集_第1张图片

你可能感兴趣的:(算法)