当前位置: 首页 > news >正文

Linux中的信号量

目录

信号量概念

定义

操作

类型

应用

信号量封装

一、创建信号量

头文件

函数原型

参数说明

返回值

示例

二、设置信号量初始值

头文件

函数原型

参数解释

返回值

示例

三、信号量的P操作

头文件

函数原型

参数解释

返回值

示例

四、信号量的V操作

示例


信号量概念

定义

        信号量是一种用于多进程 / 线程同步的整数变量,用于控制对共享资源的访问。凡是遇到内存操作就可以实现加锁。

操作

        P 操作:信号量值减 1,若值小于 0 则进程阻塞,否则继续执行。

        V 操作:信号量值加 1,若有进程阻塞则唤醒一个。

类型

        二进制信号量:值为 0 或 1,用于互斥访问。        

        ​​​​​计数信号量:值为非负整数,控制多资源访问。

应用

        互斥访问:确保同一时间只有一个进程 / 线程访问共享资源。

        资源管理:控制对多个相同资源的并发访问。

        进程同步:保证进程或线程按顺序执行。

信号量封装

1、创建/获取信号量

2、设置初始值,一般为1

3、P操作

4、V操作

一、创建信号量

        semctl 是一个在 Unix 和类 Unix 系统中用于控制信号量集的系统调用函数。

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

函数原型

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

参数说明

        key:唯一标识。

        nsems:要创建的信号量集中信号量的数量。

       semflg:标志位,用于指定创建信号量集的权限和其他选项。它可以是以下值的组合:           

                IPC_CREAT:如果信号量集不存在,则创建它。

                IPC_EXCL:与 IPC_CREAT 一起使用,如果信号量集已经存在,则返回错误。

                权限标志(如 0666):指定信号量集的访问权限。

返回值

        成功时,返回一个非负整数,即信号量集的标识符(semaphore identifier),后续的信号量操作将使用这个标识符。

        失败时,返回 -1,并设置 errno 以指示错误类型。

示例

int sem_create(key_t key, int num_sems)
{int res = 0;res = semget(key, num_sems, IPC_CREAT | 0666);if (res < 0){perror("semget error");}return res;
}

二、设置信号量初始值

        semctl 是类 Unix 系统中用于控制信号量集的一个系统调用,借助它能够对信号量集进行多种操作,例如设置信号量的值、获取信号量的值、删除信号量集等。

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

函数原型

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

参数解释

        semid:信号量集的标识符,由 semget 函数返回,用于指定要操作的信号量集。

        semindex:为第几个信号量设置值。

        cmd:要执行的命令,常见的命令如下:

                SETVAL:把单个信号量的值设置为传入的参数值。

                GETVAL:获取单个信号量的值。

                SETALL:设置信号量集中所有信号量的值。

                GETALL:获取信号量集中所有信号量的值。

                IPC_RMID:删除信号量集。

        ...:这是可选参数,依据 cmd 的不同而有所不同。在使用 SETVAL 或 SETALL 时,需要传入对应的参数值。通常使用 union semun 类型的变量来传递该参数,union semun 的定义如下:

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) */
};

返回值

        成功时,依据 cmd 的不同返回不同的值。例如,GETVAL 命令返回信号量的值,IPC_RMID 命令成功时返回 0。

        失败时,返回 -1,并设置 errno 以指示错误类型。

示例

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 sem_setval(int semid, int semindex, int val)
{union semun arg;arg.val = val;int res = semctl(semid, semindex, SETVAL, arg);if (res < 0){perror("semctl error");}return res;
}

三、信号量的P操作

        semop 是类 Unix 系统中用于对信号量集进行操作的系统调用,它允许进程原子性地对一个或多个信号量进行改变,常用于实现进程间的同步和互斥。

头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

函数原型

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

参数解释

        semid:信号量集的标识符,由 semget 函数返回,用于指定要操作的信号量集。

        sops:一个指向 struct sembuf 类型数组的指针,struct sembuf 结构体定义了对信号量的具体操作,其结构如下:

struct sembuf 
{unsigned short sem_num;  // 信号量集中信号量的编号,从 0 开始short          sem_op;   // 对信号量的操作值short          sem_flg;  // 操作标志
};

        sem_num:指定要操作的信号量在信号量集中的编号。

        sem_op:表示对信号量的操作值,有以下几种情况:

                若 sem_op 为正数,则表示释放相应数量的资源,信号量的值会增加 sem_op

                若 sem_op 为负数,则表示请求相应数量的资源,信号量的值会减少 sem_op。若信号量当前值小于 |sem_op|,则进程可能会阻塞,具体取决于 sem_flg

                若 sem_op 为 0,则表示等待信号量的值变为 0。

        sem_flg:操作标志,常用的标志有:

                IPC_NOWAIT:若操作不能立即执行,则不阻塞,直接返回错误。

                SEM_UNDO:当进程终止时,系统会自动撤销该进程对信号量的操作。

        nsopssops 数组中元素的个数,即要执行的操作数量。

返回值

        成功时,返回 0。

        失败时,返回 -1,并设置 errno 以指示错误类型。

示例

// 3、信号量的P操作
int sem_p(int semid, int semindex)
{int res = 0;struct sembuf buf = { semindex,-1,SEM_UNDO };res = semop(semid, &buf, 1);if (res < 0){perror("sem_p error");}return res;
}

四、信号量的V操作

        v操作唯一的变化就是从-1变成+1

示例

// 4、信号量的V操作
int sem_v(int semid, int semindex)
{int res = 0;struct sembuf buf = { semindex,1,SEM_UNDO };res = semop(semid, &buf, 1);if (res < 0){perror("sem_p error");}return res;
}
http://www.xdnf.cn/news/44443.html

相关文章:

  • 健身房管理系统设计与实现(springboot+ssm+vue+mysql)含万字详细文档
  • 01.04、回文排序
  • AI日报 - 2025年04月21日
  • 高效获取淘宝实时商品数据:API 接口开发与数据采集实战指南
  • Vue3核心源码解析
  • nvm管理node版本 与 nvm常用指令的使用
  • SpringBoot3集成ES8.15实现余额监控
  • Docker镜像仓库
  • 深拷贝和浅拷贝的区别
  • React Router V7使用详解
  • LeetCode[232]用栈实现队列
  • PySide6 GUI 学习笔记——常用类及控件使用方法(常用类矩阵QRect)
  • Hello, Dirty page
  • 【Flutter】使用LiveKit和Flutter构建实时视频聊天应用
  • Linux操作系统--进程的创建和终止
  • java面试篇(常见的集合底层原理)
  • 中国占全球工业机器人装机量的52%,国产机器人崛起加速洗牌,拆分机器人业务独立上市,软硬件协同增强,AI工业机械臂催生业务再增长
  • Opencv图像处理:轮廓检测、轮廓近似、绘制外接圆外接矩形
  • Linux学习——TCP
  • Viper配置管理笔记
  • 基于springboot+vue的仓库管理系统
  • AI日报 - 2025年04月19日
  • 《Operating System Concepts》阅读笔记:p748-p748
  • C# 类型、存储和变量(用户定义类型)
  • python pdf转图片再OCR
  • WebSocket启用备忘
  • 【C++】类和对象之日期类的实现(构造、运算符重载)
  • Deepseek输出的内容如何直接转化为word文件?
  • PFLM: Privacy-preserving federated learning with membership proof证明阅读
  • mysql中的group by用法详解