为何预加载至dash的共享库fini函数未被调用?
为何dash中共享库的卸载函数fini未被调用?
环境与测试代码
使用最新版本的Ubuntu Linux系统。
共享库代码 shared.c
#include <fcntl.h> #include <sys/stat.h> void init() { open("init", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); } void fini() { open("fini", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); }
编译命令
gcc -shared -fPIC -Wl,-init=init -Wl,-fini=fini shared.c -o shared.so
测试步骤与结果
$ rm init fini $ LD_PRELOAD=$PWD/shared.so dash /dev/null $ echo $? 0 $ ls init init $ ls fini ls: cannot access 'fini': No such file or directory
测试结果:共享库的加载函数init被正常调用(生成了init文件),但卸载函数fini未被调用(未生成fini文件)。若将dash替换为bash,两个函数都会被触发执行。即使改用__attribute__((destructor))标记终止函数,dash下仍不会调用。
补充系统信息
$ file $(which dash) /usr/bin/dash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f7ab02fc1b8ff61b41647c1e16ec9d95ba5de9f0, for GNU/Linux 3.2.0, stripped $ ldd $(which dash) linux-vdso.so.1 (0x00007ffd931c0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6b19e84000) /lib64/ld-linux-x86-64.so.2 (0x00007f6b1a0ec000)
原因解释
dash作为轻量级shell,为了极致的性能和资源占用优化,在进程退出时直接调用*_exit()系统调用,而非标准C库的exit()*函数。
- *exit()*函数会触发完整的用户态清理流程:包括调用所有已注册的atexit处理函数、刷新stdio缓冲区,以及通知动态链接器调用共享库的终止函数(
fini段或__attribute__((destructor))标记的函数)。 - _exit()则会直接向内核请求终止进程,跳过所有用户态的清理操作,动态链接器没有机会执行共享库的卸载逻辑,因此fini函数不会被调用。
内容的提问来源于stack exchange,提问作者Mark Galeck
相关产品推荐
相关产品推荐

