LINUX.ORG.RU

Сохранить состояние в crt между вызовами dlopen/dlclose, не изменяя main-программу

 , , , ,


0

1

В документации к встраиванию интерпретатора перла в свою прогу, скажем, на C сообщается, что необходимо манипулировать C runtime environment. Это приводит к тому, что инициализировать/деинициализировать можно только один раз. При попытке сделать это два раза - облом. Пробовал выгружать эту процедуру в разделяемую библиотеку и дёргать её dlopen/dlclose - не помогает. Перлу удаётся как-то сохранить инфу о том, что его уже один раз старт-стопнули.

Значит, можно как-то из плагина, скажем, узнать сколько раз он был загружен, не изменяя(!) test_dl.c? Вот минимальный образец. Вопрос: как?

test_dl.c

#include <stdio.h>
#include <dlfcn.h>

typedef void (*Func)(void);

const char *filename = "libdl_func.so.1.0.0";

int main(int argc, char *argv[], char **env)
{
        void *plugin_handle;
        int i;

        for (i = 0; i < 2; i++) {
                plugin_handle = dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
                if (!plugin_handle) {
                        printf("failed to load library!\n");
                        return 1;
                }
                Func func = (Func) dlsym(plugin_handle, "func");
                func();
                dlclose(plugin_handle);
        }

        return 0;
}

dl_func.c:

#include <stdio.h>

void func()
{
        printf("called\n");
        //printf("load count=%d\n", ???);
}

makefile

CC=gcc
CFLAGS=-Wall -g

all: libdl_func.so.1.0.0 test_dl

libdl_func.so.1.0.0: dl_func.o
        $(CC) -o $@ $^ -shared -Wl,-soname,libdl_func.so.1
#       ln -s libdl_func.so.1.0.0 libdl_func.so.1

dl_func.o: dl_func.c
        $(CC) $(CFLAGS) -fPIC -c dl_func.c

test_dl: test_dl.o
        $(CC) -o $@ $^ -ldl

test_dl.o: test_dl.c
        $(CC) $(CFLAGS) -c $<

clean:
        rm -f libdl_func.so.1.0.0 libdl_func.so.1 dl_func.o test_dl.o test_dl

★★★★★

#include <stdio.h>
#include <stdlib.h>

void func(void)
{
    char *s = getenv("__loadcount");
    int loadcount = s ? atoi(s) : 1;
    char buf[16];

    printf("called\n");
    printf("load count=%d\n", loadcount);

    sprintf(buf, "%d", loadcount + 1);
    setenv("__loadcount", buf, 1);
}
Deleted ()
Ответ на: комментарий от Deleted

Спасибо, это действительно вариант решения. Но сейчас, распечатывая содержание environ, проверил, что перл там ничего не меняет. Ещё варианты? Может, кроме environ, есть ещё какие-нибудь extern переменные или без asm не обойтись?

gag ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.