Linux共享库实现类似Windows DllMain的初始化逻辑
Windows DllMain(DLL_PROCESS_ATTACH)的Linux等效实现探索
需求背景
正在将大型Windows项目移植到Linux,需要实现与Windows中DllMain(DLL_PROCESS_ATTACH)等效的功能:该函数会在C运行时(CRT)初始化完成后调用,此时所有跨编译单元的全局静态变量已完成初始化,能在main()执行前或dlopen返回前完成复杂初始化操作。
已尝试方案及遇到的问题
__attribute__((init_priority)):默认未指定该属性的全局静态变量优先级为最大值0xFFFF,无法设置更高的优先级,因此无法让目标初始化函数在所有常规全局静态变量初始化之后执行(给除目标外所有静态变量设置更低优先级不现实)。- 全局对象构造/析构函数:尝试通过带
init_priority(65535)的全局对象实现初始化,但默认全局变量的优先级就是65535,无法保证该对象在所有跨编译单元的全局对象之后构造。 __attribute__((constructor)):同样无法确保初始化函数的执行晚于所有全局静态变量的初始化。- 直接注册到
.init_array段:测试代码能正常被调用,但仅在当前编译单元(TU)的初始化序列最后执行,无法将其放在整个库的.init_array段末尾,达不到全局最后执行的效果。测试代码如下:
static void init(int argc, char **argv, char **envp) { puts(__FUNCTION__); } __attribute__((section(".init_array"), used)) static typeof(init) *init_p = init;
关于ELF init/fini机制的疑问
- CRT的初始化/反初始化是否通过ELF的init/fini机制实现?
- 注册自定义的init/fini函数是否会覆盖默认的CRT初始化/反初始化函数(因为init/fini没有链式调用)?
- 如果会覆盖,该如何自行完成CRT的初始化/反初始化?
- 当前的实现思路是否完全错误?
附全局对象实现尝试的代码
struct InitDeinit { InitDeinit(void) { /* 初始化操作 */ } ~InitDeinit() { /* 反初始化操作 */ } }; namespace { InitDeinit __attribute__ ((init_priority (65535))) tco; // tco=TheChosenOne }
内容的提问来源于stack exchange,提问作者albert
相关产品推荐
相关产品推荐

