IO进线程:信号灯

二值信号灯:值为0或1。与互斥锁类似,资源可用时值为1,不可用时值为0。

计数信号灯:值在0到n之间。用来统计资源,其值代表可用资源数

等待操作是等待信号灯的值变为大于0,然后将其减1;而释放操作则相反,用来唤醒等待资源的进程或者线程

System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。而Posix信号灯指的是单个计数信号灯

System V 信号灯由内核维护

主要函数semget,semop,semctl

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>

#define WRITE 0    # 生产者编号
#define READ 1     # 消费者编号

union semun {
    int              val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                (Linux-specific) */
};


int main(int argc, char *argv[])

    //1、创建共享内存
    key_t key = ftok(".", 'a');
    if (key < 0)
    {
        perror("ftok");
        return -1;
    }
//  int shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT|0777);
    int shmid = shmget(key, 1024, IPC_CREAT|0777);
    if (shmid < 0)
    {
        perror("shmget");
        return -1;
    }
    //2. 把共享内存映射到用户空间
    char *addr = shmat(shmid, NULL, 0);
    if ((void *)-1 == addr)
    {
        perror("shmat");
        return -1;
    }
    //初始化信号灯集:可生产不可消费 编号:0:生产者  1:消费者
    int semid = semget(IPC_PRIVATE, 2, IPC_CREAT|0777);
    if (semget < 0)
    {
        perror("semget");
        return -1;
    }
    union semun sem0 = {1};
    semctl(semid, WRITE, SETVAL, sem0);  //生产者初始值:1
    union semun sem1 = {0};
    semctl(semid, READ, SETVAL, sem1);  //消费者初始值:0
    
    pid_t pid;
    if (0 > (pid = fork()))
    {
        perror("fork");
        return -1;
    }
    else if (0 == pid)  //生产者
    {
        while (1)
        {
            //申请生产者的资源
            struct sembuf sem0 = {WRITE, -1, 0};  //生产者:P操作
            semop(semid, &sem0, 1);

            printf("Input: ");
            fgets(addr, 1024, stdin);
            //释放消费者资源
            struct sembuf sem1 = {READ, 1, 0}; //消费者:V操作
            semop(semid, &sem1, 1);
            
            if (strncmp(addr, "quit", 4) == 0)
                break;
        }
        exit(0);
    }
    //消费者
    while (1)
    {
        //申请消费者资源
        struct sembuf sem1 = {READ, -1, 0};  //消费者:P操作
        semop(semid, &sem1, 1);
        
        printf("Recv: %s\n", addr);
        //释放生产者资源
        struct sembuf sem0 = {WRITE, 1, 0};  //生产者:V操作
        semop(semid, &sem0, 1);

        if (strncmp(addr, "quit", 4) == 0)
            break;
    }
    //3. 解除映射
    sleep(1);
    if (0 > shmdt(addr))
    {
        perror("shmdt");
        return -1;
    }
    //4. 销毁共享内存
    if (0 > shmctl(shmid, IPC_RMID, NULL))
    {
        perror("shmctl");
        return -1;
    }

    if (0 > semctl(semid, IPC_RMID, 0))
    {
        perror("semctl");
        return -1;
    }

    return 0;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

এ᭄星辰

混口饭吃。。。。。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值