一次仅访问一个可执行文件以访问 .so 库中的函数
Posted
技术标签:
【中文标题】一次仅访问一个可执行文件以访问 .so 库中的函数【英文标题】:Accessing only one executable at a time to a function in .so library 【发布时间】:2021-12-11 01:37:32 【问题描述】:我正在开发一个可以一起运行(并通过 ROS 通信)的可执行文件系统。我有一个所有可执行文件通用的 .json 配置文件和一个 libCommon.so,它是一个从 .json 读取某些值的函数库。该库静态链接到 CMakeLists.txt 中的所有可执行文件:
set(NAME exec1)
target_link_libraries($NAME ... Common)
随着系统的启动,所有的 exec 都需要一个接一个地启动——就像 bash 脚本中的那样:
./exec1 & ./exec2
等等
问题
我使用的 .json 解析器给了我断言错误,我发现这是可执行文件运行其构造函数并一次访问相同的配置文件的症状;
所以,我尝试了一些具有全局互斥锁(std::mutex busy)的东西,它在标头中声明并在 libCommon.so 的 cpp 中定义。然后,它在每个函数的入口处被锁定并在返回语句之前解锁:
Common.h
namespace jsonFunctions
extern std::mutex busy;
namespace ROS
extern double readRosRate( configFiles::fileID configID );
...
class ConfigFile
public:
ConfigFile( configFiles::fileID configID )
configFileFstream.open( configFiles::filePaths.at( configID ) );
if( configFileFstream.is_open() )
parsedFile.parse( configFileFstream );
~ConfigFile()
configFileFstream.close();
public:
jsonxx::Object parsedFile;
private:
std::fstream configFileFstream;
;
Common.cpp
namespace jsonFunctions
std::mutex busy;
namespace ROS
double readRosRate( configFiles::fileID configID )
busy.lock();
ConfigFile* desiredConfigFile = new ConfigFile( configID );
auto rosConfig = desiredConfigFile->parsedFile.get< jsonxx::Object >( "ROS" );
delete desiredConfigFile;
busy.unlock();
return rosConfig.get< jsonxx::Number >( "rate" );
但这不起作用。 我应该如何阻止可执行文件同时访问配置文件?
【问题讨论】:
删除desiredConfigFile 是否也会关闭文件?如果不是这种情况,构造函数会尊重多路复用器,但是当第二个构造函数尝试使用它时,您尝试保护的资源将保持打开状态。 是的,如 sn-p~ConfigFile() configFileFstream.close(); 目前我最好的猜测是互斥锁没有做任何事情,而可执行文件同时访问该文件。类似的问题已在***.com/questions/49381583/… 处得到解决,尽管一般建议不要这样做(即使您想读取共享文件而不是写入它,所以问题必须更少)。 AFAIK,Linux 共享库中唯一共享的是只读代码。如果库使用全局变量,每个进程都会获得自己的副本。这意味着,您的每个可执行文件都使用自己的std::mutex
变量,它们不会相互影响。对您开放的一种选择是在本地文件系统中使用lock file。另一种选择是使用IPC Semaphore。
参见:baeldung.com/linux/file-locking
【参考方案1】:
可执行文件存在于它们自己的内存空间中。它们不与其他可执行文件共享内存,即使它们都使用同一个共享库1。
标准 C++ 中没有进程间互斥锁。您必须从标准之外找到一个进程间互斥锁。
boost 有它们,大多数 OS 文件系统 API 都可以用来创建它们。
某些操作系统 API 允许您以独占模式打开文件。其他人依赖于您创建的显式锁。在某些情况下,此功能可能取决于您访问的文件系统,甚至取决于您访问它的方式。
显然one way 这样做是在你们共享的特定位置打开open("unique_name.lock", O_CREAT|O_EXCL, 0777)
。一次只能有一个进程以这种方式打开unique_name.lock
。
另一个是使用flock。
1 好吧,只读页面有时会被某些操作系统在进程之间共享;像可执行代码。甚至读写页面也可以在写时复制共享。然而,这种分享只是“好像”没有发生一样发生。此外,地址空间布局随机化使这种优化变得不那么有用。
【讨论】:
非常感谢,我使用了羊群作为我的目的,它的工作就像魅力:)以上是关于一次仅访问一个可执行文件以访问 .so 库中的函数的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 进程注入工具开发 ( 注入代码分析 | 获取注入的 libbridge.so 动态库中的 load 函数地址 并 通过 远程调用 执行该函数 )
Android 逆向Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )(代