Linux上具有单独数据段的多个库实例

时间:2017-07-25 05:25:31

标签: c linux linker

我有一些充满全局变量的C代码,我需要将它与我的项目链接在一起。这个外部项目是一个经常更新的实时项目,因此重写代码以使其更加多实例友好并不是一个简单的选择。举一个具体的例子,假设我们有库代码(忽略不安全!):

// foo.c
static char s_memory[256];
static int s_length;

void foo_init(char **mem)
{
    *mem = s_memory;
}

void foo_calc(char *mem)
{
    s_length = strlen(mem);
}

int foo_result()
{
    return s_length;
}

使用如下:

// test_foo.c
char *data;
foo_init(&data);
strcpy(data, "Hello, world!");
foo_calc(data);
printf("%s is %d characters long!\n", data, foo_result());

这适用于单线程实例,但我们的团队希望在多线程环境中运行它,显然这是非常错误的:

char *data1;
char *data2;
foo_init(&data1);
foo_init(&data2);
strcpy(data1, "Hello, world!");
strcpy(data2, "Goodbye cruel world!");
foo_calc(data1);
foo_calc(data2);
printf("%s and %s are %d and %d characters long!\n",
       data1, data2, foo_result(), foo_result());

我希望我们能做的就是:

char *data1;
char *data2;
FOO_HANDLE inst1 = new_instance("foo.so");
FOO_HANDLE inst2 = new_instance("foo.so");
inst1.foo_init(&data1);
inst2.foo_init(&data2);
strcpy(data1, "Hello, world!");
strcpy(data2, "Goodbye cruel world!");
inst1.foo_calc(data1);
inst2.foo_calc(data2);
printf("%s and %s are %d and %d characters long!\n",
       data1, data2, inst1.foo_result(), inst2.foo_result());

如何实现这样的目标?

1 个答案:

答案 0 :(得分:0)

最简单的解决方案是将_Thread_local(或__thread)放在每个全局上,并从其自己的线程访问每个实例。

可能有效的另一个方法是每次需要新实例时创建.so文件的新副本,dlopen。或者你可以编写自己的ELF加载器,允许同一个库的多个实例(不像它听起来那么难)。

所有这些都是糟糕的黑客,你真的应该修复代码以删除所有全局变量。