Linux 系统下的进程间通信 IPC 入门 「中」

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/39XQUQtGC3Ow-0s0JKWnog

信号量

信号量一般用于配合共享内存的数据传输,共享内存被多个进程之间共享访问,各个进程对共享内存的访问必须被同步才安全和有效。

申请信号量资源时,返回的是一组信号量集合,包含多个信号量,信号量 id 对应的是信号量集合,而不是单个信号量,每个信号量可以分别控制各种同步。信号量通过序号指定,序号从 0 开始。

系统范围内,可以申请的最多信号量集合数为 32000 个,每个信号量集合最多包含的信号量为 32000 个,每个信号量调用的最大操作数是 500,信号量值最大可达 32767。如果需要查看限制值,可以:

$ cat /proc/sys/kernel/sem

通过 semget() 申请信号量集合,参数 key 指定 IPC key,参数 nsems 指定包含的信号量数量。参数 semflg = IPC_CREAT | IPC_EXCL 指定尝试创建信号量,如果已经存在则返回失败,失败后可重新尝试获取。

int semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
if (-1 == semid) {  // failuresemid = semget(key, nsems, 0666);if (-1 == semid) {printf("semget %s", strerror(errno));}
}

信号量通过请求(抢占)和释放来控制进程间同步,本质上就是满足一定条件下对信号量值的加减。每个信号量有一些关联的变量,比如信号量值 semval。

请求信号量

/*** @brief           请求信号量* @param id        信号量集合 id* @param semindex  信号量序号,从 0 开始* @param val       信号量值偏移绝对值,一般为 1*/
void sem_set_wait(int id, int semindex, short val)
{int ret;struct sembuf buf;buf.sem_num = semindex;// P(sv) 减1 获取信号量buf.sem_op  = (-1) * val;buf.sem_flg = 0;while ((ret = semop(id, &buf, 1))&& (errno == EINTR));if (ret == -1) {perror("semop");}
}

请求信号量,也就是常说的 P 操作,实际是对信号量值做减法操作,如果当前信号量值比减数的绝对值小,那么一般情况下会阻塞当前线程。是否阻塞可以通过设置标志 sembuf.sem_flg 来决定。

释放信号量

/*** @brief           释放信号量* @param id        信号量集合 id* @param semindex  信号量序号,从 0 开始* @param val       信号量值偏移绝对值,一般为 1*/
void sem_set_signal(int id, int semindex, short val)
{struct sembuf buf;buf.sem_num = semindex;// V(sv) 加1 释放信号量buf.sem_op  = val;buf.sem_flg = 0;if (semop(id, &buf, 1) == -1) {perror("semop");}
}

释放信号量,也就是常说的 V 操作,实际是对信号量值做加法操作,不会阻塞当前线程。

最佳实践

如果有两个数据生产消费端,一个生产端和一个消费端,为了实现先生产再消费,消费完再生产,以及以此类推的同步流程,那么可以从信号量集合中使用其中的两个信号量,比如信号量 0 和信号量 1。

生产端:

// 请求信号量 0
sem_set_wait(semid, 0, 1);// 生产 ...// 释放信号量 1
sem_set_signal(semid, 1, 1);

消费端:

// 请求信号量 1
sem_set_wait(semid, 1, 1);// 消费 ...// 释放信号量 0
sem_set_signal(semid, 0, 1);

请求信号量 0,那么信号量 0 应该先被释放,信号量 1 同理。生产端生产前需要请求信号量 0,消费端消费前需要请求信号量 1,生产完成后释放信号量 1,消费完成后释放信号量 0。意味着生产前必须先消费,消费前必须先生产。

这样子相互依赖的逻辑决定了必须另一端执行完毕,当前端才可以开始执行。

既然是相互依赖,就必须有切入点,那么实际运行开始时,需要先允许生产端请求到信号量,可以设置信号量 0 的值为 1,这样生产端就可以顺利请求信号量 0 并开始生产,生产完成后再释放信号量 1,接着消费端才能够顺利请求到信号量 1。

设置信号量的值需要用到 semctl():

#include <sys/sem.h>
union semun {/* Value for SETVAL */int              val;/* Buffer for IPC_STAT, IPC_SET */struct semid_ds *buf;/* Array for GETALL, SETALL */unsigned short  *array;/* Buffer for IPC_INFO (Linux-specific) */struct seminfo  *__buf;
};int semctl(int semid, int semnum, int cmd, ...);

semctl() 有 4 个参数,semid 指定信号量集合 id,semnum 指定信号量集合中的信号量序号,cmd 指定对信号量的操作命令,最后一个参数可选。

semctl() 可用于信号量的各种设置,当 cmd = SETVAL 时,设置共用体 semun 类型的 val 成员为信号量的目标值,然后值传递 semun 类型变量给 semctl() 最后一个参数,代码如下

/*** @brief       初始化信号量值* @param id        信号量集合 id* @param semindex  信号量序号,从 0 开始* @param val       信号量初始值* @return int  0:成功,-1:失败*/
int sem_init(int id, int semindex, int val)
{union semun su;su.val = val;if (semctl(id, semindex, SETVAL, su) == -1) {perror("semctl");return -1;}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大型网站系统架构演化实例_3.使用服务集群改善网站并发处理能力

1.使用服务集群改善网站并发处理能力 使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器的处理能力、存储空间不足时&#xff0c;不要企图去更换更强大的服务器&#xff0c;对大型网站而言&#xff0c;不管多么强大的服务器&#xff0c;对大型网站而言&…

【Linux】—管理、设置防火墙规则(firewalld详解)

【Linux】—管理、设置防火墙规则&#xff08;firewalld详解&#xff09; 一、firewalld1.1 服务的启动、停止1.2 查看和设置默认区域1.3 使用firewalld进行规则配置1.4 重新加载防火墙配置1.5 查询已开放的端口、已允许的服务 &#x1f496;The Begin&#x1f496;点点关注&am…

【k8s】:kubectl 命令设置简写启用自动补全功能

【k8s】&#xff1a;kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Kubernetes&#xff08;K8s&#xff09;是一个强大的容器编排平台&#…

【WP】猿人学4 雪碧图、样式干扰

https://match.yuanrenxue.cn/match/4 探索 首先打开Fiddler&#xff0c;发现每个包的除了page参数一样&#xff0c;然后重放攻击可以实现&#xff0c;尝试py复现 Python可以正常拿到数据&#xff0c;这题不考请求&#xff0c;这题的难点原来在于数据的加密&#xff0c;这些数字…

数据库设计的三范式

简单来说就是&#xff1a;原子性、唯一性、独立性 后一范式都是在前一范式已经满足的情况进行附加的内容 第一范式&#xff08;1NF&#xff09;&#xff1a;原子性 存储的数据应不可再分。 不满足原子性&#xff1a; 满足原子性&#xff1a; 第二范式&#xff08;2NF&#xf…

Hadoop大数据处理技术-Linux相关命令

​7.Linux常用命令 1&#xff09;Windows中的dir&#xff1a;列出当前目录下所有的文件和目录 2&#xff09;cd&#xff1a;改变当前目录 cd命令并不能直接实现这种跳跃转换目录的功能 它只能让你在当前目录和其子目录之间来回切换 就像在一张平面地图上移动一样 如果想跨目录…

Biome 1.7 发布,支持从 ESLint 和 Prettier 迁移

近日&#xff0c;Biome v1.7 正式发布&#xff01;这个新版本提供了从 ESLint 和 Prettier 迁移的简单路径。它还引入了格式化程序和 linter 的实验性机器可读报告、新的 linter 规则和许多修复。 使用以下命令更新 Biome&#xff1a; npm install --save-dev --save-exact b…

【计算机毕业设计】学习平台功能介绍——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

穿越物联网的迷雾:深入理解MQTT协议

目录标题 1、MQTT简介核心特性 2、MQTT的工作原理通信过程 3、MQTT的消息质量&#xff08;QoS&#xff09;4、安全机制5、实践应用环境准备示例项目发布者客户端订阅者客户端 6、最佳实践7、结论8、参考资料 在物联网&#xff08;IoT&#xff09;的海洋中&#xff0c;数据像水流…

密码学 | 椭圆曲线密码学 ECC 入门(四)

目录 正文 1 曲线方程 2 点的运算 3 求解过程 4 补充&#xff1a;有限域 ⚠️ 知乎&#xff1a;【密码专栏】动手计算双线性对&#xff08;中&#xff09; - 知乎 ⚠️ 写在前面&#xff1a;本文属搬运博客&#xff0c;自己留着学习。注意&#xff0c;这篇博客与前三…

MySQL行级锁——技术深度+1

引言 本文是对MySQL行级锁的学习&#xff0c;MySQL一直停留在会用的阶段&#xff0c;需要弄清楚锁和事务的原理并DEBUG查看。 PS:本文涉及到的表结构均可从https://github.com/WeiXiao-Hyy/blog中获取&#xff0c;欢迎Star&#xff01; MySQL行级锁 行级锁&#xff08;Row-…

KV Cache 技术分析

原文&#xff1a;Notion – The all-in-one workspace for your notes, tasks, wikis, and databases. 1 什么是KV Cache LLM&#xff08;大型语言模型&#xff09;中的 Attention 机制中的 KV Cache&#xff08;键值缓存&#xff09;主要作用是存储键值对&#xff0c;以避免在…