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

如何阻止多可执行程序并发访问.so库函数及共享配置文件?

根因分析

你使用的std::mutex属于进程内线程互斥锁,仅能同步同一进程下的不同线程,而你启动的exec1、exec2是完全独立的进程,且libCommon是静态链接到每个可执行程序的,每个进程都会持有独立的mutex副本,互不影响,因此锁完全不生效。

可选解决方案

方案1:修改启动脚本为串行启动(成本最低)

你当前的启动写法./exec1 & ./exec2会同时启动两个进程,直接调整为按序启动,每个进程启动完成后再启动下一个,从根源避免启动阶段的并发访问:

./exec1 &
# 等待进程启动完成(可根据实际启动耗时调整等待时长,或者用pgrep判断进程状态)
sleep 0.5
./exec2 &
sleep 0.5
# 其余进程依次类推

该方案无需修改代码,仅适用于配置文件仅在进程启动阶段读取的场景。

方案2:使用跨进程互斥锁

替换std::mutex为系统级跨进程互斥机制,Linux环境下可以用POSIX有名信号量实现:

// Common.cpp 新增头文件与逻辑
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>

namespace jsonFunctions
{
// 全局唯一的信号量名称,必须以/开头,长度不超过NAME_MAX
const char* CONFIG_LOCK = "/json_config_global_lock";

namespace ROS
{
double readRosRate( configFiles::fileID configID )
{
    // 打开/创建有名信号量,初始值为1表示空闲
    sem_t* lock = sem_open(CONFIG_LOCK, O_CREAT, 0666, 1);
    if (lock == SEM_FAILED) {
        // 自行补充错误处理逻辑
        return 0.0;
    }
    // 加锁
    sem_wait(lock);
    
    ConfigFile* desiredConfigFile = new ConfigFile( configID );
    auto rosConfig = desiredConfigFile->parsedFile.get< jsonxx::Object >( "ROS" );
    delete desiredConfigFile;
    
    // 解锁
    sem_post(lock);
    sem_close(lock);
    // 注意:不要在这里调用sem_unlink,否则其他进程持有的锁会直接失效
    return rosConfig.get< jsonxx::Number >( "rate" );
}
}
}

可以在系统全局停止脚本中执行sem_unlink("/json_config_global_lock")清理残留的信号量资源。

方案3:使用文件锁同步访问

基于操作系统的文件锁机制实现同步,兼容性更强,无需额外维护锁资源:

// Common.cpp 新增头文件,修改ConfigFile构造逻辑
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>

ConfigFile::ConfigFile( configFiles::fileID configID )
{
    const char* path = configFiles::filePaths.at(configID).c_str();
    int fd = open(path, O_RDONLY);
    if (fd < 0) {
        // 补充文件打开失败处理逻辑
        return;
    }
    // 加排他锁,确保同一时间只有一个进程访问文件
    flock(fd, LOCK_EX);
    
    configFileFstream.open(path);
    if( configFileFstream.is_open() )
    {
        parsedFile.parse( configFileFstream );
    }
    // 关闭文件描述符会自动释放锁,也可以主动调用flock(fd, LOCK_UN)解锁
    close(fd);
}

如果配置文件只会被读取不会被修改,也可以把LOCK_EX换成LOCK_SH共享读锁,允许多个进程同时读取,性能更好。

方案4:预加载配置到共享内存

如果配置文件读取频次很高,可以在所有业务进程启动前,先启动一个预加载进程把配置内容读到共享内存中,所有业务进程直接从共享内存读取配置,完全避免文件并发访问问题,适合高性能要求场景。

内容的提问来源于stack exchange,提问作者Tomasz Małachowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:45:06