linux 信号量semget/semop/semctl

news2024/12/29 23:56:42

  

  • 专栏内容:linux下并发编程
  • 个人主页:我的主页
  • 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

目录

前言

概述

原理机制

接口说明

代码演示

结尾


前言

本专栏主要分享linux下并发编程相关知识,包括多进程,多线程,进程/线程间通信,并发同步控制,以及高并发下性能提升,请大家多多留言。


概述

信号量提供了多任务间的同步机制,生产者产生后,消费者才能消费,避免消费者提前消费的问题。

原理机制

信号量通过对信号量值的增,减操作来达到同步,也就是通常所说的P,V操作原语。一般P操作会消费信号量值,当信号量值不够消费时就会阻塞等待,V操作会增加信号量值,当信号量值达到上限时就是阻塞等待。

限制说明:

对于信号量,操作系统提供以下几个值来限制数量。

SEMMIN  整个操作系统,信号量id的最大数量

SEMMSL  每个信号量id下,最大的信号量个数

SEMMNS 整个操作系统中信号量的最大数量,当然也受上面两个值的约束

以上值可以查看 /proc/sys/kernel/sem

里面值的含义分别为:

 SEMMSL  同上

 SEMMNS 同上 , 大概是SEMMIN  * SEMMNI 

 SEMOPM  op操作中可以操作的,信号量数量的最大值

 SEMMNI  同上

[senllang@localhost semphore]$ cat /proc/sys/kernel/sem

32000   1024000000      500     32000

接口说明

/* 头文件 */

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

      /* 创建信号量 */

      int semget(key_t key, int nsems, int semflg);

     key, 使用 IPC_PRIVATE, 或者调用ftok产生;

     nsems, 获取或创建的数量,一般都为1;

      semflg, 与其它IPC的flag类似,可以设置为IPC_CREAT若不存在时可以创建,如果或IPC_EXCL值,存在时就会报错。

      /* 设置或删除信号量  */

      int semctl(int semid, int semnum, int cmd, ...);

其中cmd可以取值 :

IPC_RMID,删除semid对应的信号量,同时唤醒所有semop等待

IPC_STAT,获取信号量信息,最后用以下结构作为最后一个参数进行传出。

 struct semid_ds {

               struct ipc_perm sem_perm;  /* Ownership and permissions */

               time_t          sem_otime; /* Last semop time */

               time_t          sem_ctime; /* Last change time */

               unsigned long   sem_nsems; /* No. of semaphores in set */

           };

IPC_SET,设置权限等信息,最一个参数用以下结构传入。

 struct ipc_perm {

               key_t          __key; /* Key supplied to semget(2) */

               uid_t          uid;   /* Effective UID of owner */

               gid_t          gid;   /* Effective GID of owner */

               uid_t          cuid;  /* Effective UID of creator */

               gid_t          cgid;  /* Effective GID of creator */

               unsigned short mode;  /* Permissions */

               unsigned short __seq; /* Sequence number */

           };

    

    /* 信号量操作 */

   int semop(int semid, struct sembuf *sops, size_t nsops);

     int semtimedop(int semid, struct sembuf *sops, size_t nsops,

                      const struct timespec *timeout);

    有两种op操作接口,一种不带时间,一种可以设置超时时间。

 struct sembuf有三个成员,分别为:

unsigned short sem_num;  /* semaphore number */
short          sem_op;   /* semaphore operation */
short          sem_flg;  /* operation flags */

sem_flag 可以取值 :

IPC_NOWAIT,不会等待;

 SEM_UNDO,在进程结束时,会回退op操作

sem_op, 当>0时会增加信号值;当=0时,会等零值时才返回;当<0时,会减少信号量值,不足时会等待;

代码演示

这个程序创建一个包含 1 个信号量的集合,初始化信号量的值为 1,然后创建一个子进程。子进程等待信号量,然后输出一条信息,最后增加信号量的值。父进程也等待信号量,输出一条信息,然后增加信号量的值;最后销毁信号量。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>

int main(int argc, char const *argv[])
{
    int semid;

    // 创建一个包含 1 个信号量的集合
    semid = semget(IPC_PRIVATE, 1, 0666);

    if (semid == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    // 初始化信号量的值为 1
    if (semctl(semid, 0, SETVAL, 1) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    // 创建一个子进程
    if (fork() == 0) {
        struct sembuf sops;

        // 子进程等待信号量
        sops.sem_num = 0;
        sops.sem_op = -1;
        sops.sem_flg = 0;

        if (semop(semid, &sops, 1) == -1) {
            perror("semop");
            exit(EXIT_FAILURE);
        }

        printf("Child process is working\n");

        // 子进程增加信号量的值
        sops.sem_num = 0;
        sops.sem_op = 1;
        sops.sem_flg = 0;

        if (semop(semid, &sops, 1) == -1) {
            perror("semop");
            exit(EXIT_FAILURE);
        }

        exit(EXIT_SUCCESS);
    } else {
        struct sembuf sops;

        // 父进程等待信号量
        sops.sem_num = 0;
        sops.sem_op = -1;
        sops.sem_flg = 0;

        if (semop(semid, &sops, 1) == -1) {
           perror("semop");
            exit(EXIT_FAILURE);
        }

        printf("Parent process is working\n");

        // 父进程增加信号量的值
        sops.sem_num = 0;
        sops.sem_op = 1;
        sops.sem_flg = 0;

        if (semop(semid, &sops, 1) == -1) {
            perror("semop");
            exit(EXIT_FAILURE);
        }

        // 销毁信号量
        if (semctl(semid, 0, IPC_RMID, 0) == -1) {
            perror("semctl");
            exit(EXIT_FAILURE);
        }

        exit(EXIT_SUCCESS);
    }

    return 0;
}
     

输出结果如下:

[senllang@localhost semphore]$ gcc ex01_sem.c
[senllang@localhost semphore]$ ./a.out
Parent process is working
Child process is working
semop: Invalid argument
 


结尾

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。另外有什么想要了解的内容,也可以给我发邮件,互相谈讨,定知无不言。

注:未经同意,不得转载!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/453692.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于 多态 的职工管理系统(Staff Management System)

目录 一、管理系统需求 作用&#xff1a;管理公司内所有员工的信息 分类&#xff1a;要显示每位员工的编号、姓名、岗位与职责 具体实现的功能&#xff1a; 二、创建管理 类 三、各个接口函数 1、菜单展示功能 2、 选择功能 3、创建员工功能 ①普通员工employee ②经理…

【Web3.0大势所趋】我看到了互联网未来的模样

前言 Web3.0 是一个越来越受到关注的话题&#xff0c;它被认为将会带来天翻地覆的变化。本文我们一起来谈谈 Web3.0 的概念、特点和优势&#xff0c;并探讨它为什么如此重要和具有革命性的。 文章目录 前言Web3.0是什么Web3.0的技术Web3.0的优势总结 Web3.0是什么 Web3.0: 是下…

尚硅谷Kafka

Kafka 1.Kafka概述1.1 定义1.2 消息队列1.2.1 传统消息队列的应用场景1.2.2 消息队列的两种模式 1.3 kafka基础架构 2.快速入门2.1 kafka环境安装2.2 kafka命令行操作参数2.2.1 主题命令行操作 2.2.2 生产者命令行操作2.2.3 消费者命令行操作 3.Kafka 生产者3.1 生产者消息发送…

Vue3+Vite神器:按需引入自定义组件unplugin-vue-components

前言 我们做项目时&#xff0c;会封装大量的公共组件&#xff0c;如果我们每一个都去在maints里面引入&#xff0c;非常麻烦不说&#xff0c;代码也不优雅。所以更好的方法就是自动注册全局组件&#xff0c;在组件中直接使用就好。 一种方法是自己在components文件夹下新建in…

QML控件--MenuBar

文章目录 一、控件基本信息二、控件使用三、属性成员四、成员函数 一、控件基本信息 Import Statement&#xff1a;import QtQuick.Controls 1.4 Since&#xff1a;Qt 5.1 二、控件使用 MenuBar&#xff1a;是菜单栏&#xff0c;通常&#xff0c;菜单静态声明为菜单栏的子项&…

redis入门必会知识

Redis基础知识目录 5、sortedSet 文章目录 系列文章目录前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 一、redis是什么&#xff1f; Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务 ! 是一个开源的使用ANSI C语言编写…

【C++】——- 模板初阶介绍

前言&#xff1a; 在之前的学习中&#xff0c;我们已经把 C前期所需要用到的知识都给大家介绍了一遍。接下来&#xff0c;我们要学习的就是关于在C 中模板的基本知识&#xff0c;今天我带给大家的内容便是关于 模板初阶的介绍。 目录 &#xff08;一&#xff09; 泛型编程 &…

【Python_Opencv图像处理框架】图像形态学操作

写在前面 本篇文章是opencv学习的第三篇文章&#xff0c;主要讲解了图像的形态学有关操作&#xff0c;作为初学者&#xff0c;我尽己所能&#xff0c;但仍会存在疏漏的地方&#xff0c;希望各位看官不吝指正❤️ 写在中间 读完这篇文章后&#xff0c;相信您便能信手拈来下面图…

给照片换底色(python+opencv)

给照片换底色&#xff08;pythonopencv&#xff09; 本篇目录&#xff1a; &#x1f984; 一、分析照片基本信息 &#x1f984; 二、方法一&#xff08;遍历图像&#xff0c;将像素值点替换修改为指定颜色&#xff09; &#x1f984; 三、修改图片颜色方法二&#xff08;先转…

MySQL数据库索引

目录 0.知识回顾 1.数据库约束 一.索引 1.什么是索引 2.为什么要使用索引(作用) 3.索引的使用场景 4.如何使用索引 1.查看索引 2.创建索引 3.修改索引 4.删除索引 5.索引的分类 1.使用场景不同 2.按列区分 3.按数据组织方式 二.索引的数据结构 1.HASH 2.二叉搜…

如何设计自动化测试框架?阿里P7工程师耗时一个月总结而成

目录 一、什么是自动化测试框架 二、自动化测试框架的架构设计 三、自动化测试框架的最佳实践 四、自动化测试框架的组成部分 五、自动化测试框架的设计原则 六、如何选择自动化测试框架 七、自动化测试框架实例 八、结论 一、什么是自动化测试框架 自动化测试框架是一…

UE4/5多人游戏详解(八、游戏模式和游戏状态里的函数重写,插件内地图的地址做变量,做变量让按钮出现不同状态,插件内的所有代码)

目录 这里不写在插件里面&#xff0c;而是在游戏模式&#xff1a; 头文件&#xff1a; Cpp文件&#xff1a; 更改ini文件 进入地图设置模式&#xff1a; 写插件里面&#xff0c;做一个变量&#xff1a; 写变量 然后更改函数MenuSet&#xff1a; 在子系统中做变量&…

FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(四)

接着同样地我们也需要完成对千兆网口ETH模块和USB2.0模块的编写&#xff0c;实际上和UART串口模块的设计思想大同小异&#xff0c;也同样地需要完成两项关键功能即识别并解析报文、接收并发送数据&#xff0c;千兆网口ETH和USB2.0的底层驱动在前面的例程中也详细说明了&#xf…

常用的设计模式(单例模式、工厂模式等)

1.单例模式 概述: 在有些系统中&#xff0c;为了节省内存资源、保证数据内容的一致性&#xff0c;对某些类要求只能创建一个实例&#xff0c;这就是所谓的单例模式. 例如&#xff0c;Windows 中只能打开一个任务管理器&#xff0c;这样可以避免因打开多个任务管理器窗口而造…

Centos切换jdk版本

先安装了jdk1.8的版本&#xff0c;需要使用jdk17的版本 1.先安装jdk17&#xff0c;再配置环境变量&#xff1a; vim ~/.bashrc 2.在最后一行添加 ##这个添加的就是路径&#xff0c;一定要和自己jdk安装的路径是一致的 export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 3.然…

Mybatis框架超详解及运用总结

Mybatis 一、什么是Mybatils&#xff1f;二、第一个Mybatils程序2.1、创建springboot工程2.2、准备数据2.3、配置MyBatis2.4、编写SQL语句2.5、单元测试 三、JDBC四、数据库连接池五、lombok六、Mybatis基础操作6.1、删除6.2、新增6.2.1、主键返回 6.3、修改6.4、查询6.4.1、数…

【AI绘画】AI绘画的创意应用

目录 1.引言2.将AI生成的图像转化为数字艺术品2.1AI生成的画作拍卖2.2将AI生成的图像转化为雕塑 3.将AI生成的图像用于虚拟场景的创建3.1使用GAN生成虚拟人物3.2在虚拟场景中使用AI生成的图像 1.引言 当今的AI绘画技术已经发展到了让人惊艳的程度&#xff0c;不仅可以生成高质量…

【每日一题Day183】LC1187使数组严格递增 | dp

使数组严格递增【LC1187】 给你两个整数数组 arr1 和 arr2&#xff0c;返回使 arr1 严格递增所需要的最小「操作」数&#xff08;可能为 0&#xff09;。 每一步「操作」中&#xff0c;你可以分别从 arr1 和 arr2 中各选出一个索引&#xff0c;分别为 i 和 j&#xff0c;0 <…

缓存优化----SpringCache

spring cache spring Cache介绍 spring cache是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单地加一个注解&#xff0c;就能实现缓存功能。 Spring cache提供了一层抽象&#xff0c;底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不…

springboot JWT 搭建授权服务器

目录 0 基本介绍 0.1 课程视频 0.2 架构逻辑图 0.2.1 登录JWT与授权服务器交互 0.2.2 登录成功后JWT与gateway-server交互 路由限制 1 JWT私钥公钥 1.1 安装git ->win系统右键 -> git bash here 1.2 生成私钥jks文件 1.3 用私钥jks文件解析出公钥 1.4 保存 BEGI…