【发布时间】:2018-07-15 13:51:20
【问题描述】:
在我的程序中,我计算了一个全局变量并生成了一个加载共享库的子程序(这是 SSCCE,所以它很愚蠢,但可能是最小的示例)。
main.c
编译
gcc main.c common.o -o program:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
extern char **environ;
extern int g_common;
int main() {
char *argv[2] = {"/bin/true", NULL};
// SSCCE HACK: don't do this at home!
// environ[0] is unimportant so we replace it
environ[0] = "LD_PRELOAD=/tmp/foobar.so";
g_common = 1;
printf("main: g_common is %d\n", g_common);
if (!fork())
execve(*argv, argv, environ);
}
全局变量定义在
common.c用gcc -fPIC -rdynamic -c common.c编译:
int g_common;
dyno 库是
foobar.c用
gcc -shared -fPIC -Wl,-init,init common.o foobar.c -o /tmp/foobar.so:
#include <stdio.h>
extern int g_common;
void init() {
printf("foobar.so: g_common is %d\n", g_common);
}
现在你可以猜到我在这里要做什么了。
主要是 program 我想计算一些东西,这里是 g_common 。实际上,这是一个很长的计算,所以我只想做一次。
然后在程序的稍后部分,我生成子程序,动态预加载库,并在该库中使用先前计算的值。
这里只是一个程序,但实际上有数千个程序,我不想每次都在预加载库的 init() 函数中重新计算 g_common 值。
当然,我尝试做的事情不起作用,程序打印 1 但子程序打印 0(未初始化)。那是因为g_common 有两个实例。
好的,那么如何正确地做到这一点,所以我只计算一次g_common?
【问题讨论】:
-
你不能那样做,执行擦除几乎所有你以前的程序。像管道一样使用 IPC。
-
当您使用
execve()时,您无能为力。用新进程替换当前进程意味着g_common被重置为 0。如果要跨进程调用共享值,则需要查看共享内存,或者将值保存在文件并在替换过程中从文件中读取它,或者其他一些 IPC 机制。
标签: c linux shared-libraries ld-preload