【问题标题】:How best to share a global computed in main with a dynamically loaded library?如何最好地与动态加载的库共享 main 中的全局计算?
【发布时间】: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.cgcc -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


【解决方案1】:

我使用了 Jonathan Leffler 的建议来使用共享内存。我想将此作为对未来新手的好处发布。

所有功劳都应该归功于乔纳森·莱弗勒,而不是我。

main():

int fd;
fd = shm_open("g_common", O_CREAT | O_WRONLY, 
        S_IWUSR | S_IWGRP | S_IWOTH);
write(fd, "foo", 4);

foobar.cinit():

int fd = shm_open("g_common", O_RDONLY, 0);
void *bytes = mmap(NULL, 4, PROT_READ, MAP_SHARED, fd, 0 );
printf("g_common is %s\n", (char *)bytes);

当然也不需要common.c

【讨论】:

    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    相关资源
    最近更新 更多