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

如何查询关联System V共享内存的进程数?及写冲突检测方法

System V共享内存:1写N读模型的互斥实现及关联进程数查询

一、避免多进程同时写入的实现方案

针对1写N读模型,核心是保证同一时间只有一个写进程操作共享内存,以下是几种可靠实现方式:

1. System V二元信号量(推荐)

利用System V信号量实现互斥锁,和共享内存同属一套IPC机制,集成性好:

// 初始化信号量(仅需执行一次,比如由第一个启动的进程完成)
#include <sys/sem.h>
#include <sys/ipc.h>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

key_t sem_key = ftok("/tmp/shm_sem", 'W');
int sem_id = semget(sem_key, 1, IPC_CREAT | 0666);
union semun init_arg;
init_arg.val = 1; // 二元信号量初始值设为1
semctl(sem_id, 0, SETVAL, init_arg);

// 写进程获取锁
struct sembuf lock_op = {0, -1, SEM_UNDO};
semop(sem_id, &lock_op, 1);
// --- 开始写入共享内存 ---
// ... 你的写入逻辑 ...
// --- 写入结束 ---
// 释放锁
struct sembuf unlock_op = {0, 1, SEM_UNDO};
semop(sem_id, &unlock_op, 1);

SEM_UNDO选项会在进程异常退出时自动释放信号量,避免死锁。

2. 共享内存内的原子变量

在共享内存头部嵌入原子整数,通过原子CAS操作实现互斥,无需额外IPC资源:

#include <stdatomic.h>
#include <sys/shm.h>

// 定义共享内存结构
typedef struct {
    _Atomic int write_in_progress; // 0=无写入,1=正在写入
    char data[4096]; // 实际存储的数据
} ShmBlock;

// 写进程尝试获取写入权限
int shm_id = shmget(shm_key, sizeof(ShmBlock), 0666);
ShmBlock *shm_ptr = shmat(shm_id, NULL, 0);

int expected = 0;
if (atomic_compare_exchange_strong(&shm_ptr->write_in_progress, &expected, 1)) {
    // 获取到写入权限,执行操作
    memcpy(shm_ptr->data, "your_data", strlen("your_data")+1);
    // 操作完成后重置标记
    atomic_store(&shm_ptr->write_in_progress, 0);
} else {
    // 已有其他写进程在运行,执行重试或报错逻辑
}

该方式依赖C11标准的原子操作,Linux下GCC/Clang均支持。

3. 文件锁(简单易用)

通过文件独占锁实现互斥,无需依赖System V信号量,适合快速原型开发:

#include <fcntl.h>
#include <unistd.h>

// 写进程获取锁
int lock_fd = open("/tmp/shm_write_lock", O_CREAT | O_RDWR, 0666);
struct flock write_lock = {
    .l_type = F_WRLCK,
    .l_whence = SEEK_SET,
    .l_start = 0,
    .l_len = 0 // 锁定整个文件
};
// 阻塞等待获取锁,非阻塞可用F_SETLK
fcntl(lock_fd, F_SETLKW, &write_lock);

// --- 写入共享内存 ---
// ... 你的写入逻辑 ...
// --- 写入结束 ---

// 释放锁
write_lock.l_type = F_UNLCK;
fcntl(lock_fd, F_SETLK, &write_lock);
close(lock_fd);

二、查询共享内存关联的进程数量

Linux系统提供了两种方式获取System V共享内存的关联进程数(即nattch值):

1. 解析/proc/sysvipc/shm文件

该文件记录了所有System V共享内存的元数据,直接读取解析即可:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>

int get_shm_attached_count(key_t shm_key) {
    FILE *fp = fopen("/proc/sysvipc/shm", "r");
    if (!fp) return -1;

    char line[256];
    // 跳过表头行
    fgets(line, sizeof(line), fp);

    while (fgets(line, sizeof(line), fp)) {
        key_t current_key;
        int nattch;
        // 按文件格式解析,注意不同内核版本格式可能略有差异
        if (sscanf(line, "%*d %x %*d %*d %*d %*d %d", &current_key, &nattch) == 2) {
            if (current_key == shm_key) {
                fclose(fp);
                return nattch;
            }
        }
    }

    fclose(fp);
    return -1; // 未找到对应共享内存
}

2. 调用ipcs命令解析输出

通过popen()执行ipcs -m命令,再解析输出结果,适合脚本或快速调试:

# shell命令示例,替换为你的共享内存key(十六进制)
ipcs -m | grep <your_shm_key> | awk '{print $6}'

在C程序中可以通过popen()调用并读取输出,逻辑类似文件解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 06:23:11