我有一个旧的应用程序,它使用pthread库中的pthread_atfork函数来注册子钩子。我正在将应用程序移动到使用glibc 2.14.90的新构建环境。 pthread_atfork似乎在2002年基本上从pthread库中删除了,我们创建的一个共享库将不再编译。
以下是相关代码:
void
_init(void)
{
static int first = 1;
if ( first ) {
pthread_atfork(NULL,NULL,_init);
first = 0;
}
{
pthread_t tid;
pthread_create(&tid,0,startUp,0);
}
return;
}
pthread_atfork调用将_init注册为子钩子,每次有一个fork时都要在子进程中运行。 Init只是创建一个新线程来执行startUp,这是一个初始化函数,用于设置文件,互斥体,初始化参数读取等内容......
由于pthread_atfork隐藏在glibc 2.14中,是否有另一种方法来注册相同类型的钩子,以便init在fork运行?我宁愿使用标准的lib而不做任何修改,以保持构建环境的可移植性。
glibc 2.14源代码在这里,对于那些感兴趣的人(pthread_atfork文件在nptl目录下):
我收到的编译错误:
gcc -g -nostartfiles -o mto.so -shared -I mto.c -lnsl -lresolv -lrt -lm -lpthread -ldl
/ usr / bin / ld:/usr/lib/libpthread_nonshared.a(pthread_atfork.oS):重定位R_386_GOTOFF对未定义的隐藏符号`__dso_handle'在制作共享对象时不能使用
$ gcc -v
使用内置规格。 COLLECT_GCC = GCC COLLECT_LTO_WRAPPER =的/ usr /的libexec / GCC / i686的-红帽-LINUX / 4.6.3 / LTO-包装 目标:i686-redhat-linux 配置为:../ configure --prefix = / usr --mandir = / usr / share / man --infodir = / usr / share / info --with-bugurl = http://bugzilla.redhat.com/bugzilla --enable-bootstrap - -enable-shared --enable-threads = posix --enable-checking = release --with-system-zlib --enable -__ cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable- linker-build-id --enable-languages = c,c ++,objc,obj-c ++,java,fortran,ada,go,lto --enable-plugin --enable-java-awt = gtk --disable-dssi - -with-java-home = / usr / lib / jvm / java-1.5.0-gcj-1.5.0.0 / jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar = / usr / share / java / eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune = generic --with-arch = i686 --build = i686-红帽Linux的 线程模型:posix gcc版本4.6.3 20120306(Red Hat 4.6.3-2)(GCC)
$ ldd --version
ldd(GNU libc)2.14.90 版权所有(C)2011 Free Software Foundation,Inc。 这是免费软件;查看复制条件的来源。没有 保证;甚至不适用于适销性或特定用途的适用性。 由Roland McGrath和Ulrich Drepper撰写。
$ nm /usr/lib/libpthread.a|grep -C 1 atfork
00008150 W __pread64
000060b0 T __pthread_atfork
00002ab0 T __pthread_attr_destroy
--
00007ba0 W __recvmsg
U __register_atfork
00008c10 T __res_state
--
00008150 W pread64
000060b0 T pthread_atfork
00002ab0 T pthread_attr_destroy
$ nm /usr/lib/libpthread_nonshared.a
pthread_atfork.oS:
U _GLOBAL_OFFSET_TABLE_
w __dso_handle
00000000 T __i686.get_pc_thunk.bx
00000000 T __pthread_atfork
U __register_atfork
00000000 T pthread_atfork
感谢您的时间。
答案 0 :(得分:1)
您的问题是外包装函数pthread_atfork
似乎已移至libpthread_nonshared.a
,以便它可以识别调用它的库,可能是因为如果/当时,可以删除已安装的处理程序库已卸载,它通过引用您有意省略的起始文件中定义的__dso_handle
符号来实现此目的。 您无法执行此操作。省略启动文件仅对某些低级别目的有效;它与链接标准库的任何部分都不兼容。
显然你使用-nostartfiles
的原因是能够编写自己的_init
函数,该函数将在加载库时运行,因为没有-nostartfiles
它会导致链接器错误由于crti.o
中与同名函数的冲突。不幸的是,这是错误的解决方法。
重新定义_init
以在库加载时运行代码是一个不受支持的黑客,很久以前就被弃用了。在库加载时运行代码的正确方法是将__attribute__((__constructor__))
应用于要运行的函数。为函数指定一个不会与任何内容冲突的名称,或者只是将其设为static
,这样您就不必担心其名称冲突。