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

GNU Linux单写多读进程场景下文件访问同步问题及代码有效性确认问询

多进程文件读写的同步问题分析

你完全是对的——这段代码绝对无法保证读进程能稳定读取到正确的TestValue,你的担忧非常合理,用命名信号量来做同步确实是解决这类跨进程访问问题的可靠方案。

先拆解下当前代码的核心问题:

  • 写操作完全没有原子性:它先打开文件清空内容(写入10个空字符),关闭后再重新打开写入TestValue。这两步之间存在明显的时间窗口,读进程完全可能在间隙中读取到空内容。
  • 多进程访问无同步机制:哪怕没有上述间隙,读进程也可能在写进程刚写入部分数据时就开始读取,拿到不完整的数值;如果有多个写进程同时操作,文件内容会彻底混乱。
  • 小细节提醒:代码里的文件权限0x7770建议改成八进制07770,这是Linux权限的标准写法,避免误解。

接下来聊下怎么用命名信号量修复这个问题:
命名信号量是跨进程同步的绝佳选择,它通过全局名称实现不同进程间的识别与共享,能完美解决这类竞态问题。

写进程的改造思路

  1. 创建/打开命名信号量,初始值设为1(相当于互斥锁)
  2. 调用sem_wait()获取信号量(进入临界区,加锁)
  3. 把两次open/close合并成一次操作,直接定位到文件开头覆盖写入,彻底消除中间的时间间隙
  4. 调用sem_post()释放信号量(退出临界区,解锁)
  5. 不再使用信号量时记得销毁它

改造后的写进程代码示例:

#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <string>

#define SEM_NAME "/test_value_sem"

int wr2f(const std::string& f_name, const uint16_t TestValue) { 
    // 创建/打开命名信号量,初始值1,权限0666
    sem_t* sem = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0666, 1);
    if (sem == SEM_FAILED) {
        // 信号量已存在,直接打开
        sem = sem_open(SEM_NAME, 0);
        if (sem == SEM_FAILED) return -1;
    }

    // 获取信号量,进入临界区
    if (sem_wait(sem) == -1) {
        sem_close(sem);
        return -1;
    }

    // 一次打开文件并覆盖写入
    int f = open(f_name.c_str(), O_CREAT | O_RDWR | O_TRUNC, 07770); 
    if (f < 0) {
        sem_post(sem);
        sem_close(sem);
        return -1;
    }

    char c[10]; 
    memset(c, 0, sizeof(c)); 
    sprintf(c, "%d", TestValue); 
    write(f, c, strlen(c)); 
    close(f); 

    // 释放信号量,退出临界区
    sem_post(sem);
    sem_close(sem);

    return 0; 
}

读进程的对应同步操作

读进程也需要遵循同样的同步逻辑:

  1. 打开同一个命名信号量
  2. 调用sem_wait()加锁
  3. 读取文件内容
  4. 调用sem_post()解锁
  5. 关闭信号量

这样就能保证同一时刻只有一个进程(读或写)在访问文件,彻底避免竞态条件导致的读取错误。

最后补充:如果写进程是长期运行的,或者不再需要信号量时,记得调用sem_unlink(SEM_NAME)销毁信号量,避免系统资源残留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 06:37:57