首页/新闻资讯/正文详情

第16讲:System V - 基于建造者模式的信号量

发布时间:2026/11/6 7:54:33 来源:云帆数科 栏目:资讯中心
第16讲:System V - 基于建造者模式的信号量
目录1. 信号量和P、V原语2. 信号量操作接口3. 封装Sem1. 信号量和 P、V 原语信号量和P、V原语由Dijkstra迪杰斯特拉提出。1.1 信号量常规理解执行流间互斥与同步。1.2 信号量值含义S 0S表示可用资源的个数。S 0表示无可用资源、无等待进程。S 0|S|表示等待队列中的进程个数。1.3 信号量结构体伪代码// 信号量本质上是一个计数器 struct semaphore { int value; pointer_PCB queue; };1.4 P 原语P(s) { s.value--; if (s.value 0) { // 将该进程状态置为等待状态 // 将该进程的 PCB 插入相应等待队列 s.queue 的末尾 } }1.5 V 原语V(s) { s.value; if (s.value 0) { // 唤醒相应等待队列 s.queue 中等待的一个进程 // 改变其状态为就绪态 // 将其插入 OS 就绪队列 } }1.6 信号量集结构体Thesemid_dsdata structure is defined insys/sem.has follows:structsemid_ds{structipc_permsem_perm;/* Ownership and permissions */time_tsem_otime;/* Last semop time */time_tsem_ctime;/* Last change time */unsignedlongsem_nsems;/* No. of semaphores in set */};Theipc_permstructure is defined as follows (the fieldsuid,gid, andmodeare settable usingIPC_SET):structipc_perm{key_t__key;/* Key supplied to semget(2) */uid_tuid;/* Effective UID of owner */gid_tgid;/* Effective GID of owner */uid_tcuid;/* Effective UID of creator */gid_tcgid;/* Effective GID of creator */unsignedshortmode;/* Permissions */unsignedshort__seq;/* Sequence number */};2. 信号量操作接口2.1 semgetNAMEsemget- get a System V semaphore set identifierSYNOPSIS#includesys/types.h#includesys/ipc.h#includesys/sem.hintsemget(key_tkey,intnsems,intsemflg);RETURN VALUEIf successful, the return value will be thesemaphore set identifier(a nonnegative integer), otherwise,-1is returned, witherrnoindicating the error.参数介绍key信号量集的键值同消息队列和共享内存。nsems信号量集中信号量的个数。semflg同消息队列和共享内存。2.2 semctlNAMEsemctl- System V semaphore control operationsSYNOPSIS#includesys/types.h#includesys/ipc.h#includesys/sem.hintsemctl(intsemid,intsemnum,intcmd,...);This function has three or four arguments, depending oncmd. When there are four, the fourth has the typeunion semun.The calling program must define this union as follows:unionsemun{intval;/* Value for SETVAL */structsemid_ds*buf;/* Buffer for IPC_STAT, IPC_SET */unsignedshort*array;/* Array for GETALL, SETALL */structseminfo*__buf;/* Buffer for IPC_INFO (Linux-specific) */};RETURN VALUEOn failure,semctl()returns-1witherrnoindicating the error.Otherwise, the system call returns a nonnegative value depending oncmdas follows:GETNCNT: the value ofsemncnt.GETPID: the value ofsempid.GETVAL: the value ofsemval.GETZCNT: the value ofsemzcnt.IPC_INFO: the index of the highest used entry in the kernel’s internal array recording information about all semaphore sets. This information can be used with repeatedSEM_STATorSEM_STAT_ANYoperations to obtain information about all semaphore sets on the system.SEM_INFO: as forIPC_INFO.SEM_STAT: the identifier of the semaphore set whose index was given insemid.SEM_STAT_ANY: as forSEM_STAT.All othercmdvalues return0on success.参数介绍semid由semget返回的信号集标识码。semnum信号集中信号量的序号。semctl()performs the control operation specified bycmdon the System V semaphore set identified bysemid, or onthesemnum-th semaphore of that set. The semaphores in a set are numberedstarting at0.cmd将要采取的动作具体动作查看man手册。2.3 semopNAMEsemop,semtimedop- System V semaphore operationsSYNOPSIS#includesys/types.h#includesys/ipc.h#includesys/sem.hintsemop(intsemid,structsembuf*sops,size_tnsops);semop()performs operations on selected semaphores in the set indicated bysemid. Each of thensopselements in the array pointed to bysopsis a structure that specifies an operation to be performed on a single semaphore.The elements of this structure are of typestruct sembuf, containing the following members:unsignedshortsem_num;/* semaphore number */shortsem_op;/* semaphore operation: -1, P 操作; 1, V 操作 */shortsem_flg;/* operation flags */Flags recognized insem_flgareIPC_NOWAITandSEM_UNDO.If an operation specifiesSEM_UNDO, it will be automatically undone when the process terminates.RETURN VALUEIf successful,semop()andsemtimedop()return0; otherwise they return-1witherrnoindicating the error.参数介绍semid该信号量的标识码也就是semget函数的返回值。sops指向一个sembuf结构的指针。nsopssops数组中的操作项数量可在一次semop调用中提交多个操作。3. 封装 Sem我们使用信号量简化信号量使用测试使用二元信号量对显示输出进行互斥打印。3.1 Sem.hpp#pragmaonce#includeiostream#includestring#includememory#includecstdlib#includesys/types.h#includesys/ipc.h#includesys/sem.h#includeunistd.hconststd::string pathname/tmp;intproj_id0x77;#defineGET_SEMIPC_CREAT// 不给权限#defineBUILD_SEM(IPC_CREAT|IPC_EXCL|0666)// 只关注使用和删除classSemaphore{public:Semaphore(intsemid,intflag):_semid(semid),_flag(flag){}voidP(){structsembufsb;// 该结构系统提供sb.sem_num0;sb.sem_op-1;sb.sem_flgSEM_UNDO;intn::semop(_semid,sb,1);(void)n;}voidV(){structsembufsb;sb.sem_num0;sb.sem_op1;sb.sem_flgSEM_UNDO;intn::semop(_semid,sb,1);(void)n;}~Semaphore(){if(_flagGET_SEM)return;// 让信号量自动销毁// 如果销毁信号量集合The argument semnum is ignoredintn::semctl(_semid,0,IPC_RMID);(void)n;std::coutsem set destroy!std::endl;}private:int_semid;int_flag;};usingsem_sptrstd::shared_ptrSemaphore;// 使用简单的建造者模式用它来构建单 semclassSemaphoreBuilder{public:SemaphoreBuilder():_val(-1){}SemaphoreBuilderSetVal(intval){_valval;return*this;// 支持连续访问}sem_sptrBuild(intflag){// 0. 先做简单的合法性判断if(_val0){std::cerryou must init first!std::endl;returnnullptr;}// 1. 申请 key 值key_t k::ftok(pathname.c_str(),proj_id);if(k0)std::exit(1);// 2. 根据初始值创建信号量集合intsemid::semget(k,1,flag);// 只创建一个信号量就够用了if(semid0)std::exit(2);if(BUILD_SEMflag){// 3. 初始化信号量unionsemun// 该联合体系统不提供需要我们自己定义{intval;/* Value for SETVAL */structsemid_ds*buf;/* Buffer for IPC_STAT, IPC_SET */unsignedshort*array;/* Array for GETALL, SETALL */structseminfo*__buf;/* Buffer for IPC_INFO (Linux-specific) */}un;un.val_val;// 设置为初始值intn::semctl(semid,0,SETVAL,un);if(n0)std::exit(3);}// 4. 创建并返回信号量集合returnstd::make_sharedSemaphore(semid,flag);}~SemaphoreBuilder(){}private:int_val;// 所有信号量的初始值};3.2 Writer.cc测试信号量接口#includeSem.hpp#includecstdio#includecstdlib#includetime.h#includeunistd.hintmain(){SemaphoreBuilder sb;autofsemsb.SetVal(1).Build(BUILD_SEM);// 创建一个信号量并初始化为 1当作锁使用if(fork()0){autocsemsb.Build(GET_SEM);intcnt10;while(cnt--){csem-P();printf(C);fflush(stdout);usleep(std::rand()%95270);printf(C );usleep(std::rand()%43990);fflush(stdout);csem-V();}std::exit(0);}intcnt50;while(cnt--){fsem-P();printf(F);fflush(stdout);usleep(std::rand()%95270);printf(F );usleep(std::rand()%43990);fflush(stdout);fsem-V();}return0;}3.3 结论System V信号量生命周期也是随内核的。ipcs -s ipcrm -s semid3.4 关于建造者模式

相关推荐

平面度/平整度测试服务——摄像头模组CMOS感光芯片测试方案
平面度/平整度测试服务——摄像头模组CMOS感光芯片测试方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 7:54:33

【AI写作变现】带妈妈和兄弟姐妹一起做AI,月入轻松破3W+
【AI写作变现】带妈妈和兄弟姐妹一起做AI,月入轻松破3W+

https://gitcode.com/OpenDocCN1/data/blob/master/imgs/zhuanqian_ca90cbd41766c6a951399d1aac7f451b.png 大家好,我是观星,2024年4月选择裸辞All In AI,个人定位如下: 🎖️ 前特种兵 ⌨️ AI代写变现项目 聚光矩阵… · 2026/11/6 7:54:33

我把百智办公的指令保存了七十条,常用的只有五条
我把百智办公的指令保存了七十条,常用的只有五条

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 7:54:33

Powershell远程管理服务器客户端
Powershell远程管理服务器客户端

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:49:27

Java 开发日记高级~
Java 开发日记高级~

Java.慈祥的开发日记 Java基础语法 SSM学习专栏 JDK8 新特性 Linux服务器开发使用 环境搭建🤖 Linux 基础入门学习 Docker K8S部署使用 Docker入门学习Docker网络 Git 和 Github 项目管理工具 分布式版本控制系统Git分布式版本控制系统Git 二:… · 2026/11/6 10:49:27

主模式RTL设计:状态机与三态驱动的物理实现
主模式RTL设计:状态机与三态驱动的物理实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:47:25

GitHub镜像站搭建指南:提升代码仓库访问效率
GitHub镜像站搭建指南:提升代码仓库访问效率

1. 项目背景与核心价值 国内开发者在使用GitHub时经常遇到访问不稳定、克隆速度慢等问题。搭建本地镜像站能够显著提升代码仓库的访问效率,特别适合企业级开发团队或高校实验室等需要频繁与GitHub交互的场景。不同于简单的代理方案,完整的镜像站可以实现… · 2026/11/6 10:45:21

错题本数字化与高效学习方法论
错题本数字化与高效学习方法论

1. 错题整理的价值与方法论 错题本是每个学习者都应该拥有的秘密武器。2013年的错题整理看似是过去式,但其中蕴含的学习方法论却具有永恒价值。我至今仍保留着2013年那本已经泛黄的错题本,它不仅记录了我当年的知识盲区,更见证了我的学习轨迹… · 2026/11/6 10:45:21

企业应收账款数字化管理解决方案与实施指南
企业应收账款数字化管理解决方案与实施指南

1. 应收账款管理的行业痛点应收账款管理一直是企业财务流程中最容易出问题的环节之一。根据某商业信用管理协会的调研数据显示,超过67%的中小企业都曾因应收账款管理不善导致现金流断裂。传统管理方式主要依赖Excel表格和纸质单据,业务员需要手动记录每笔… · 2026/11/6 10:45:21

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23

三菱PLC数据采集到数据库的时序设计:Python+MC协议实战
三菱PLC数据采集到数据库的时序设计:Python+MC协议实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11

ASIC主模式RTL设计:状态机与三态驱动的流片级实现
ASIC主模式RTL设计:状态机与三态驱动的流片级实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11

STM32嵌入式C++开发:GDB调试与Renode仿真实战指南
STM32嵌入式C++开发:GDB调试与Renode仿真实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:02:11

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码