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

信号量使用流程

信号量使用流程(POSIX 信号量)

1️⃣ 信号量创建与初始化

A. 命名信号量(sem_open

#include <semaphore.h>sem_t *sem;
sem_unlink("/SemChkCrt");                 // 删除可能存在的同名信号量
sem = sem_open("/SemChkCrt", O_CREAT, 0666, 1); // 创建信号量,初值为1
if (sem == SEM_FAILED) {perror("sem_open failed");
}
  • sem_unlink 删除系统中已有同名信号量,保证干净初值
  • O_CREAT 表示创建信号量,如果已存在会返回现有信号量
  • 0666 权限可读可写
  • 最后一个参数 1 是信号量初值(可用资源数量)
  • 返回值:sem_t*,失败返回 SEM_FAILED

B. 非命名信号量(sem_init

sem_t sem;
sem_init(&sem, 0, 1); // 0 表示线程间共享,1 是初值

2️⃣ 信号量使用

A. 等待资源(P 操作)

sem_wait(sem); // 阻塞直到信号量 > 0

B. 尝试获取资源(非阻塞)

if (sem_trywait(sem) == 0) {// 成功获取
} else {// 没有资源
}

C. 释放资源(V 操作)

sem_post(sem); // 信号量 +1,可能唤醒等待线程

D. 获取当前值(调试用)

int val;
sem_getvalue(sem, &val); // 获取当前信号量计数

3️⃣ 项目应用示例(y[0] + GetSemOpen)

// 创建信号量并存入数组
y[0] = (UintPtr)GetSemOpen(x, O_CREAT, 0666, 1);// 检查是否创建成功
f = PtrEqlErrChk(y[0], (UintPtr)SEM_FAILED, "错误原因", z);// 使用信号量
sem_wait((sem_t*)y[0]);  // P 操作
sem_post((sem_t*)y[0]);  // V 操作// 调试查看信号量值
set $ptr = (int*) malloc(sizeof(int))
call sem_getvalue((sem_t*)y[0], $ptr)
p *$ptr
call free($ptr)

4️⃣ 信号量释放和清理

A. 命名信号量

sem_close((sem_t*)y[0]);   // 关闭信号量句柄
sem_unlink("/SemChkCrt");  // 删除系统中的信号量名字

B. 非命名信号量

sem_destroy(&sem);

5️⃣ 使用注意事项

  1. 命名信号量可能已存在 → 用 sem_unlink 删除
  2. UintPtr 存的是指针整数 → 操作前需要强转回 (sem_t*)
  3. 调试查看值用 sem_getvalue 或 gdb 强转打印
  4. 指针算术自动按元素大小计算,不要手动乘 sizeof

bug:

现象

在多次运行测试代码的时候,会发先原本运行通过的测试代码,出现了阻塞,不往下继续运行。
在这里插入图片描述
通过gdb调试发现是程序是跑到sem_wait这一行不动的,随机打印
信号量为y[0]=0,并且调用sem_post信号量增加,
![(https://i-blog.csdnimg.cn/direct/9113c4e5bb85452aa4cac472f44dd792.png)
然后再去查看SemOpen 返回的是 sem_t*返回的值,发现信号量一创建计数值就显示为0了。这就存在两种可能

 a = sem_open(w,x,y,z);
  1. z = 1 传进去作为“资源数量”,理论上应该初始化信号量值为 1 如果 sem_getvalue 打印出来是 0,说明
    GetSemOpen 内部 没有把信号量值初始化为 c,或者初始化在 不同进程/线程

  2. 另一种可能:你使用的是命名信号量(sem_open),而系统里之前有同名信号量,O_CREAT
    会返回现有信号量,而这个信号量的值可能已经被其他线程/进程消耗掉了。

由于这是一个系统函数所以,第二种情况可能性会大一点,在这里插入图片描述
删除这个信号量,并且在测试代码末尾加上sem_unlink操作,问题解决。

http://www.dtcms.com/a/355601.html

相关文章:

  • 多媒体内容智能检索技术进展
  • [特殊字符] ​​MySQL性能参数查询总结​
  • 146-延长无线传感器网络生命周期的睡眠调度机制的混合元启发式优化方法!
  • [RK3576][Android14] Android->添加以太网MAC地址选项
  • Spring Boot 实战:接入 DeepSeek API 实现问卷文本优化
  • FFmpeg 实战:从零开始写一个简易视频播放器
  • 视频层和叠加层
  • 数据结构:冒泡排序 (Bubble Sort)
  • Android14 USB子系统的启动以及动态切换相关的init.usb.rc详解
  • mysql主从复制GTID模式
  • Day16_【机器学习—模型拟合问题】
  • AI智能能源管理系统深度剖析:从工业节能到数据中心降耗,解锁企业降本减排新方案
  • Docker 40个自动化管理脚本-1 (20/40)
  • CVPR2019 Oral论文《Side Window Filtering》解读及算法 Python 实现
  • 网络编程3-UDP协议
  • Megatron-Energon 和 Megatron-LM
  • 解锁五大联赛数据:API技术指南
  • Python在AI与数据科学工作流中的新角色:2025年实践指南
  • X-AnyLabeling:Win10上安装使用X-AnyLabeling标注工具
  • 国内永久免费云服务器有哪些?
  • AI视频生成工具全景对比:元宝AI、即梦AI、清影AI和Vidu AI
  • Java学习笔记之——通过分页查询样例感受JDBC、Mybatis以及MybatisPlus(一)
  • CPU、进程、线程上下文切换
  • 使用Rag 命中用户feedback提升triage agent 准确率
  • 特斯拉 Tesla FSD 12.6.4,FSD14, VLA 和 华为 ADS 4.0 比较
  • 广东省省考备考(第八十九天8.28)——判断推理(第九节课)
  • 智能客服多智能体(知识库问答+情绪感知+工单路由)
  • 玄机靶场 | 第九章-blueteam 的小心思3
  • openEuler中LVM调整实现home与root分区空间平衡
  • LeetCode 3446. 按对角线进行矩阵排序