前言

很久不用,基本概念虽然还记得,估计不会用了,写个demo练练手。

概念

信号量(信号灯)本质上是一个计数器,用于协调多个进程(包括但不限于父子进程)对共享数据对象的读/写。它不以传送数据为目的,主要是用来保护共享资源(信号量、消息队列、socket连接等),保证共享资源在一个时刻只有一个进程独享。

信号量是一个特殊的变量,只允许进程对它进行等待信号和发送信号操作。最简单的信号量是取值0和1的二元信号量,这是信号量最常见的形式。

通用信号量(可以取多个正整数值)和信号量集方面的知识比较复杂,应用场景也比较少。

相关函数

更多信息请通过 man 命令参考 linux 手册

NAMEsemget - get a System V semaphore set identifierSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);
NAMEsemop, semtimedop - System V semaphore operationsSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semop(int semid, struct sembuf *sops, size_t nsops);
NAMEsemctl - System V semaphore control operationsSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, ...);

接口封装

// Semaphore.h
//
// Created by zhaoyf on 2022/5/3.
//#ifndef LINUX_SEMAPHORE_H
#define LINUX_SEMAPHORE_Hnamespace Semaphore {/// 创建或者获取已存在的信号量/// \param num 要创建的信号量集中信号量数量, [0, 1, 2, ..., n-1]/// \param key 创建信号量的 key/// \return    信号量idint SemInit(int num, int key);/// p操作,信号量值减1/// \param semid 信号量idvoid SemP(int semid);/// v操作,信号量值加1/// \param semid 信号量idvoid SemV(int semid);/// 销毁信号量集中的所有信号量/// \param semid 信号量id/// \param num   信号量数量void SemRelease(int semid, int num);
}#endif //LINUX_SEMAPHORE_H
// Semaphore.cpp
//
// Created by zhaoyf on 2022/5/3.
//#include "Semaphore.h"#include <stdio.h>#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>namespace Semaphore {/* 定义自己的semun联合体*/union semun {int val;struct semid_ds *buf;unsigned short *array;struct seminfo *__buf;};/// 创建或者获取已存在的信号量/// \param num 要创建的信号量集中信号量数量, [0, 1, 2, ..., n-1]/// \param key 创建信号量的 key/// \return    信号量idint SemInit(int num, int key) {int semid = -1;semid = semget((key_t) key, num, IPC_CREAT | IPC_EXCL | 0600);if (semid == -1) {// 指定 key 信号量已存在semid = semget((key_t) 1234, 1, 0600);} else {// 设置初始值union semun a;a.val = 1;//信号量的初始值if (semctl(semid, 0, SETVAL, a) == -1) {perror("semctl error");}}return semid;}/// p操作,信号量值减1/// \param semid 信号量idvoid SemP(int semid) {struct sembuf buf;buf.sem_num = 0;buf.sem_op = -1;//pbuf.sem_flg = SEM_UNDO;if (semop(semid, &buf, 1) == -1) {perror("semop p error");}}/// v操作,信号量值加1/// \param semid 信号量idvoid SemV(int semid) {struct sembuf buf;buf.sem_num = 0;buf.sem_op = 1;//vbuf.sem_flg = SEM_UNDO;if (semop(semid, &buf, 1) == -1) {perror("semop v error");}}/// 销毁信号量集中的所有信号量/// \param semid 信号量id/// \param num   信号量数量void SemRelease(int semid, int num) {for (int i = 0; i < num; ++i) {if (semctl(semid, i, IPC_RMID) == -1) {perror("semctl del error");}}}
}

测试用例

进程一代码 a.cpp

// a.cpp
//
// Created by zhaoyf on 2022/5/4.
//
#include "Semaphore.h"#include <thread>
#include <chrono>#include <stdio.h>// 进程1代码
int main() {int semId = Semaphore::SemInit(1, 1234);const int NUM = 5;for (int i = 0; i < NUM; ++i) {Semaphore::SemP(semId);printf("a");fflush(stdout);int n = rand() % 3000;std::this_thread::sleep_for(std::chrono::milliseconds(n));printf("a");fflush(stdout);Semaphore::SemV(semId);n = rand() % 3000;std::this_thread::sleep_for(std::chrono::milliseconds(n));}return 0;
}

进程二代码 b.cpp

// b.cpp
//
// Created by zhaoyf on 2022/5/4.
//#include "Semaphore.h"#include <thread>
#include <chrono>#include <stdio.h>// 进程2代码
int main() {int semId = Semaphore::SemInit(1, 1234);const int NUM = 5;for (int i = 0; i < NUM; ++i) {Semaphore::SemP(semId);printf("b");fflush(stdout);int n = rand() % 3000;std::this_thread::sleep_for(std::chrono::milliseconds(n));printf("b");fflush(stdout);Semaphore::SemV(semId);n = rand() % 3000;std::this_thread::sleep_for(std::chrono::milliseconds(n));}return 0;
}
gcc -o a a.cpp Semaphore.cpp
gcc -o b b.cpp Semaphore.cpp./a & .boutput:
bbaabbaabbaabbaabbaabbaabbaabbaabbbbaaaa

个人代码仓库请参考: Linux: Linux学习资源汇总

Linux 进程间通信之 - 信号量相关推荐

  1. Linux进程间通信(信号量)

    ★什么是信号量 为了防止出现多个程序同时访问一个共享数据资源而引发的问题,需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区.信号量就可以提供这样一种访问机制. ...

  2. Linux进程间通信——使用共享内存

    下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...

  3. Linux多线程——使用信号量同步线程

    http://blog.csdn.net/ljianhui/article/details/10813469/ 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过是同步的对 ...

  4. linux进程间通信:system V 信号量 生产者和消费者模型编程案例

    生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据 两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个 生产者向缓冲区中填数据前需要判断缓冲区是否 ...

  5. Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

    Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...

  6. Linux进程间通信(管道、消息队列、共享内存、信号、信号量)

    目录 Linux进程间通信概述 1.管道 无名管道(pipe) 有名管道(fifo) 2.消息队列(msg) 消息队列的通信原理 消息队列相关api 消息队列收发数据 键值生成 消息队列移除 3.共享 ...

  7. 【 Linux 】进程间通信之信号量

    进程间通信方式---信号量 1.概念 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临 ...

  8. linux进程间通信:POSIX 共享内存

    文章目录 思维导图 通信原理 优势 POSIX 共享内存 编程接口 编程案例 思维导图 之前学习过sysemV 的共享内存的实现及使用原理,参考linux进程间通信:system V 共享内存 POS ...

  9. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()...

    我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...

最新文章

  1. Hyper-V的三种网卡
  2. mysql 按小时分组统计_PowerBI业务分析:按排名分组统计
  3. 一起学nRF51xx 22 -  实现一个具体SVC调用功能的demo
  4. 趣味编程:从字符串中提取信息(参考答案 - 下)
  5. gmail注册手机号不能用于验证_注册Google帐户手机号无法验证的问题
  6. boost::hana::partition用法的测试程序
  7. 腾讯TBS X5 WebView的简单使用
  8. Oracle+ASM单机环境下,开启归档的最简单的方法
  9. linux使用ping命令ping本机,Linux下使用ping命令判断网络的好坏
  10. 软考网络管理员存储容量计算相关问题
  11. cvBoundingRect的用法(转)
  12. 面料经纬向、正反面判别方法
  13. 弱键(Weak Key, ACM/ICPC Seoul 2004, UVa1618)
  14. 一维码和二维码开源库zint学习
  15. 英语语法 第一章 句子的形成——概说
  16. 2023年入学华东师范大学MBA提前面试流程及时间-文都管联院
  17. 三维数字沙盘电子沙盘MR AR VR虚拟现实无人机倾斜摄影三维全景建模卫星图片矢量
  18. vue+element 下拉框回显时间少一天
  19. 浙江大学软件学院2020年保研真题Distance of Triples (25 分)
  20. 是什么门的缩写_开车:和她结婚需要注意什么

热门文章

  1. request.getParameter乱码
  2. windows Server2016 开启多用户登录
  3. input标签disabled和readonly属性的区别
  4. 谷歌扩展漏洞赏金计划
  5. Vi编辑器的三种模式
  6. Android OTG (USB Hos) 编程
  7. 常用人体表面积计算公式(汇总)
  8. 计算机是如何识别内核态和用户态的,浅谈操作系统的用户态和内核态
  9. 新奔驰E260L融入更多年轻化元素 彰显双重性格
  10. spring-cloud