You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于共享内存/信号量的消息队列如何检测无进程连接

核心结构定义

现有消息队列结构定义如下:

typedef struct
{
    char data[MESSAGE_SIZE];
} MESSAGE;

typedef struct
{
    sem_t sem_send;
    sem_t sem_receive;
    MESSAGE messages[];
} MQ;

要实现删除队列时的存活连接检测,不需要依赖特殊内核接口,直接在共享内存中实现跨进程引用计数+删除标记即可,逻辑稳定且无额外性能开销,具体方案如下:

实现逻辑

  1. 扩展共享内存控制头
    在MQ结构体中新增3个存放在共享内存区域的字段,保证所有连接进程可见:

    • sem_lock:控制互斥信号量,初始值为1,专门用来保护引用计数、删除标记的并发读写,避免多进程同时修改导致数据错乱
    • ref_cnt:跨进程原子引用计数,记录当前已连接的进程总数。优先用C11标准的atomic_int类型,旧编译环境可以用普通int搭配GCC__atomic系列原子内置函数操作
    • delete_pending:待删除标记,用int类型即可,0表示队列正常运行,1表示队列已进入删除流程,禁止新连接接入
      修改后的结构参考:
    typedef struct
    {
        char data[MESSAGE_SIZE];
    } MESSAGE;
    
    typedef struct
    {
        sem_t sem_lock;
        sem_t sem_send;
        sem_t sem_receive;
        atomic_int ref_cnt;
        int delete_pending;
        MESSAGE messages[];
    } MQ;
    

    初始化队列时注意,sem_init的第二个参数pshared必须传1(标记信号量为跨进程共享),ref_cnt初始值设为0,delete_pending初始值设为0。

  2. 统一连接准入逻辑
    所有进程调用shmat挂载共享内存成功后,必须先走完以下校验才能开始收发消息:

    • 等待sem_lock进入临界区
    • 检查delete_pending值,如果为1,说明队列已经在删除流程中,立刻释放sem_lock、执行shmdt断开挂载,返回连接失败
    • 标记为0的话,对ref_cnt做原子加1
    • 释放sem_lock,正式完成连接建立。
  3. 统一断连逻辑
    所有进程结束队列使用、主动断开时,按以下流程执行:

    • 等待sem_lock进入临界区
    • 对ref_cnt做原子减1
    • 如果减完后ref_cnt为0,且delete_pending为1,说明当前是最后一个存活连接,直接在当前进程中执行资源回收:依次sem_destroy销毁所有信号量(sem_lock/sem_send/sem_receive)、调用shm_unlink解绑共享内存
    • 释放sem_lock,执行shmdt断开自身的共享内存挂载即可。
  4. 统一删除入口逻辑
    业务侧调用删除队列接口时,不需要等待进程退出,也不需要主动遍历系统进程,只需要打标记:

    • 等待sem_lock进入临界区
    • 将delete_pending设为1
    • 检查当前ref_cnt值,如果已经是0,说明当前没有任何存活连接,直接在当前调用流程里完成信号量销毁、shm_unlink操作
    • 释放sem_lock,执行shmdt断开自身挂载后直接返回即可。如果当前ref_cnt大于0,不需要阻塞等待,最后一个进程断开时会自动触发资源回收,不会残留泄漏。

踩坑提醒

  • 所有对ref_cnt、delete_pending的读写必须在sem_lock保护的临界区内执行,或者用严格的跨进程原子操作,绝对不能裸读裸写,否则会出现计数不准、重复销毁、内存泄漏问题
  • 所有信号量必须分配在共享内存区域,初始化时必须设置跨进程共享属性,否则多进程拿到的是独立信号量,完全起不到同步作用
  • 待删除标记设置后必须拦截所有新连接请求,避免资源已经销毁还有新进程挂载访问,触发野指针崩溃

内容的提问来源于stack exchange,提问作者Satcha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:24:24