首页 > 其他分享 >信号量

信号量

时间:2023-05-04 11:24:50浏览次数:34  
标签:index handlers int 信号量 handler printf

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


int main(void) {
    // 创建新的或者获取已有的信号量集
    /*
     * semget 创建新的或者获取已有的信号量集
     *  key: ftok函数返回的key
     *  nsems int 信号量集中信号量个数
     *  semflg 标志位置
     * */
    // 操作信号量

    /*
     * semop  操作信号量
     *  semid int semget返回的信号量ID
     *  sops struct sembuf* 操作结构数组
     *          struct sembuf {
                    unsigned short  sem_num; // 信号量在信号量集中的编号(编号从0开始)
                    short           sem_op;  // 操作数 3表示,释放资源3个,-2表示拿走资源2个
                    short           sem_flg; // 操作标志 如果标志位包含 IPC_NOWAIT,在资源不够时不等待直接返回-1,errno设置为EAGAIN
                };
     *  nsops unsigned int 操作结构数
     * */


    // 销毁信号量集
    /*
     * semctl
     * semid int msgget获取的消息队列ID
     * num  int 需要操作的信号量编号(从0开始)
     * cmd   要做的操作
     *      IPC_RMID 销毁共享内存
     *      GETALL 获取所有信号量的值 buf传入数组,通过buf获取所有值 例如: unsigned short values[4]
     *      SETALL 设置所有信号量的值 buf传入数组,通过buf设置所有值 例如: unsigned short values[4]={1,2,3,4}
     *      GETVAL 获取特定信号量的值
     *      SETVAL 设置特定信号量的值 buf传入int
     *
     *  buf NULL
     *  成功返回0 失败返回-1
     *  注:在销毁时,如果有进程阻塞在semop函数,会立即返回-1,并且errno设置为ERMID
     * */
    return 0;
}
  • 练习
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/sem.h>
#define ARR_SIZE(arr) sizeof((arr))/sizeof((arr)[0])
const unsigned short BOOK_MAX_COUNT = 8;

typedef int(*Handler)(int, int, short);

typedef struct {
    char name[128];
    short count;
    int index;
    Handler handler;
} hbuf;

int handler(int semId, int index, short count) {
    // 1. 表示未借书  2. 表示书已借完 0.表示正常 -1 表示其他错误
    // 取出当前数值做判断
    int value;
    value = semctl(semId, index, GETVAL, NULL);
    if (value == BOOK_MAX_COUNT && count > 0) {
        return 1;
    }
    if (value == 0 && count < 0) {
        return 2;
    }
    struct sembuf buf = {index, count, 0};
    return semop(semId, &buf, 1);
}

// 判断字符串是否为数字
int isNumber(char *s) {
    if (strspn(s, "1234567890") == strlen(s)) {
        return 1;
    } else {
        return 0;
    }
}

int main() {
    // 初始化图书
    char *books[5] = {"书本1", "书本2", "书本3", "书本4", "书本5"};
    // 生成KEY
    key_t key = ftok(".", 8);
    printf("%d,生成key.\n", getpid());
    // 创建信号量
    printf("%d,创建信号量.\n", getpid());
    int semID = semget(key, ARR_SIZE(books), IPC_CREAT | 0664);
    if (semID == -1) {
        perror("semget");
        return -1;
    }
    char *js = "借";
    char *hs = "还";

    // 初始化操作
    hbuf *handlers[ARR_SIZE(books) * 2] = {};
    for (int i = 0; i < (ARR_SIZE(books)); i++) {
        // 每本书有两个借还两个操作
        // 0     1    2
        // 0,1   2,3  4,5

        hbuf *j = (hbuf *) malloc(sizeof(hbuf));
        hbuf *h = (hbuf *) malloc(sizeof(hbuf));
        strcat(j->name, js);
        strcat(h->name, hs);
        strcat(j->name, books[i]);
        strcat(h->name, books[i]);
        j->count = -1;
        j->index = i;
        j->handler = handler;
        h->count = 1;
        h->index = i;
        h->handler = handler;
        handlers[i * 2] = h;
        handlers[i * 2 + 1] = j;
    }

    // 初始化信号量
    unsigned short values[ARR_SIZE(books)] = {};
    for (int i = 0; i < ARR_SIZE(books); i++) {
        values[i] = BOOK_MAX_COUNT;
    }
    semctl(semID, 0, SETALL, values);
    // 打印选项
    char *cindex = malloc(sizeof(char) * 128);
    int index;
    for (;;) {
        printf("==================\n");
        // 获取所有信号集的数量
        semctl(semID, 0, GETALL, values);
        for (int i = 0; i < ARR_SIZE(handlers); i++) {
            printf("%d.%s 剩余:%d\n", i, handlers[i]->name, values[handlers[i]->index]);
        }
        printf(">> ");
        scanf("%s", cindex);
        if (strcmp(cindex, "!") == 0) {
            printf("结束\n");
            break;
        }
        if (isNumber(cindex) == 0) {
            printf("输入不合法\n");
            continue;
        }
        index = atoi(cindex);
        if (index >= ARR_SIZE(handlers)) {
            printf("超长输入不合法\n");
            continue;
        }
        int handler_val = handlers[index]->handler(semID, handlers[index]->index, handlers[index]->count);
        if (handler_val == -1) {
            perror("handlers");
            return -1;
        } else if (handler_val == 1) {
            printf("未借书,不需要还书\n");
        } else if (handler_val == 2) {
            printf("书已借完,不能借书\n");
        }

    }
    // 释放内存
    printf("释放内存\n");
    for (int i = 0; i < ARR_SIZE(handlers); i++) {
        free(handlers[i]);
    }
    free(cindex);
    // 释放信号量集
    printf("释放信号量集\n");
    semctl(semID, 0, IPC_RMID, NULL);
}

标签:index,handlers,int,信号量,handler,printf
From: https://www.cnblogs.com/wtil/p/17370552.html

相关文章

  • 进程间通信方式———3、信号量(Semaphore)
    1.信号量信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一......
  • Linux 进程信号量 All In One
    Linux进程信号量AllInOne进程信号量processsignaldemos(......
  • 【Java 并发】【九】【AQS】【七】Semaphore信号量底层机制原理
    1 前言接下来我们来看看Semaphore,也是基于之前讲解的AQS来实现的,建立在AQS体系之上的一个并发工具类。2  Semaphore是什么Semaphore,它是一个信号量,主要作用是用来控制并发中同一个时刻执行的线程数量,可以用来做限流器,或者流程控制器。在创建的时候会指定好它有多少个信号量......
  • 《操作系统原理、实现与实践》实践项目5&6:信号量&地址映射与共享
    教员布置的操作系统的第一个大作业,其中有一些知识相对而言比较重要,包括一些操作过程都具有重复实验的价值;所以写一个blog记录一下,方便一下以后重复这个大实验或是复现。分为三个部分:实验环境的配置、实验5的实现、实验6的实现。实验环境的配置:KylinOS应该是可以实现的,实现的原......
  • 进程间通信-信号量
    资源竞争资源竞争:当多个进程在同时访问共享资源时,会产生资源竞争,最终最导致数据混乱临界资源:不允许同时有多个进程访问的资源,包括硬件资源(CPU、内存、存储器以及其他外围设备)与软件资源(共享代码段、共享数据结构)临界区:访问临界资源代码多进程对stdout资源的竞争......
  • 多线程的同步和互斥—线程的信号量
    同步://account.h#ifndef_ACCOUNT_H#define_ACCOUNT_H#include<pthread.h>#include<semaphore.h>typedefstruct{intcode;doublebalance;......
  • C# 多线程访问之 SemaphoreSlim(信号量)【进阶篇】
    C#多线程访问之SemaphoreSlim(信号量)【进阶篇】 阅读目录一、简介二、用法示例 三、属性or函数or方法释义属性-AvailableWaitHandle属性-CurrentCount......
  • 多线程编程五:信号量
    2.33.信号量的概念_哔哩哔哩_bilibili2.34.信号量的工作机制_哔哩哔哩_bilibili......
  • 【并发编程六】c++进程通信——信号量(semaphore)
     【并发编程六】c++进程通信——信号量(semaphore)一、概述二、信号量三、原理四、过程1、进程A过程2、进程B过程五、demo1、进程A2、进程B六、输出......
  • C++信号量实现线程间同步,windows使用SetEvent,linux使用sem_t,QT测试
     目录windows使用CreateEvent、SetEvent、ResetEvent、WaitForSingleObjectlinux使用sem_init、sem_wait、sem_trywait、sem_post、sem_destroy windows使用C......