一.需求:
有一个独立可执行的程序 ,之前是被exec调用执行的,想改成线程 加载.so来执行。之前对.so不够了解,不清楚so中的exit是否会导致线程退出,进而导致整个进程退出?
二.测试:
1.首先整一个so出来。
-
[root@localhost c]# cat libso_test.h
-
#ifndef _LIBSO_TEST_H_
-
#define _LIBSO_TEST_H_
-
#include <stdio.h>
-
#include <stdlib.h>
-
void libso_test_foo();
-
#endif
-
[root@localhost c]# cat libso_test.c
-
#include "libso_test.h"
-
void libso_test_foo(void)
-
{
-
printf("libso_test_foo\n");
-
exit(1);
-
}
编译:
注意-fPIC选项。PIC指Position Independent Code。共享库要求有此选项,以便实现动态连接(dynamic linking),
库文件以lib开始。共享库文件以.so为后缀。-shared表示生成一个共享库
-
gcc libso_test.c -fPIC -shared -o libso_test.so
ok,检查下lib是否生成,是否有lib_test_foo这个函数,nm这个命令nm - list symbols from object files 很有用
-
[root@localhost c]# ls libso_test.so
-
libso_test.so
-
[root@localhost c]# nm libso_test.so
-
00000000002006c0 a _DYNAMIC
-
0000000000200858 a _GLOBAL_OFFSET_TABLE_
-
w _Jv_RegisterClasses
-
0000000000200698 d __CTOR_END__
-
0000000000200690 d __CTOR_LIST__
-
00000000002006a8 d __DTOR_END__
-
00000000002006a0 d __DTOR_LIST__
-
0000000000000688 r __FRAME_END__
-
00000000002006b0 d __JCR_END__
-
00000000002006b0 d __JCR_LIST__
-
0000000000200888 A __bss_start
-
w __cxa_finalize@@GLIBC_2.2.5
-
00000000000005e0 t __do_global_ctors_aux
-
0000000000000510 t __do_global_dtors_aux
-
00000000002006b8 d __dso_handle
-
w __gmon_start__
-
0000000000200888 A _edata
-
0000000000200898 A _end
-
0000000000000618 T _fini
-
0000000000000498 T _init
-
00000000000004f0 t call_gmon_start
-
0000000000200888 b completed.6349
-
0000000000200890 b dtor_idx.6351
-
U exit@@GLIBC_2.2.5
-
0000000000000590 t frame_dummy
-
00000000000005bc T libso_test_foo
-
U puts@@GLIBC_2.2.5
-
[root@localhost c]#
2.再整个简单的test.c
-
[root@localhost c]# cat test.c
-
#include <pthread.h>
-
#include <stdio.h>
-
#include <assert.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <string.h>
-
#include <errno.h>
-
#include "libso_test.h"
-
-
-
void *t1_run(void *arg)
-
{
-
printf("t1_run\n");
-
libso_test_foo();
-
};
-
-
void *t2_run(void *arg)
-
{
-
printf("t2_run\n");
-
};
-
int main(void)
-
{
-
printf("main_start\n");
-
int ret = 0;
-
pthread_t t1,t2;
-
ret = pthread_create(&t1,NULL,t1_run,NULL);
-
assert(!ret);
-
ret = pthread_create(&t2,NULL,t2_run,NULL);
-
assert(!ret);
-
pthread_join(t1,NULL);
-
pthread_join(t2,NULL);
-
printf("main_end\n");
-
while(1)
-
;
-
return 0;
-
}
再把这个so也编译到test中 -L指定目录,-lso_test 为了链接libso_test.so,注意-l后面不用加lib了
-
gcc test.c -lpthread -L. -lso_test -o test
再检查下 test到底有没有把libso_test.so给链接进去,擦,not found
-
[root@localhost c]# ldd test
-
linux-vdso.so.1 => (0x00007fffbdfff000)
-
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003ff4400000)
-
libso_test.so => not found
-
libc.so.6 => /lib64/libc.so.6 (0x0000003ff4000000)
-
/lib64/ld-linux-x86-64.so.2 (0x0000003ff3800000)
试着执行了下,faint....
-
[root@localhost c]# ./test
-
./test: error while loading shared libraries: libso_test.so: cannot open shared object file: No such file or directory
google得知 :
这是因为操作系统无法找到库,so位于当前路径,位于库文件的默认路径之外。尽管我们在编译时(compile time)提供了.so文件的位置,但这个信息并没有写入test可执行文件(runtime)
为了解决上面的问题,我们可以将.so文件放入默认搜索路径中。但有时,特别是多用户环境下,我们不享有在默认搜索路径写入的权限。
一个解决方案是设置LD_LIBRARY_PATH环境变量。比如:
$export LD_LIBRARY_PATH=.
这样,可执行文件执行时,操作系统将在先在LD_LIBRARY_PATH下搜索库文件,再到默认路径中搜索。环境变量的坏处是,它会影响所有的可执行程序。如果我们在编译其他程序时,如果我们不小心,很可能导致其他可执行文件无法运行。因此,LD_LIBRARY_PATH环境变量多用于测试。
嗯,能found了
-
[root@localhost c]# export LD_LIBRARY_PATH=.
-
[root@localhost c]# ldd test
-
linux-vdso.so.1 => (0x00007fff810f3000)
-
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003ff4400000)
-
libso_test.so => ./libso_test.so (0x00007fc6df4c5000)
-
libc.so.6 => /lib64/libc.so.6 (0x0000003ff4000000)
-
/lib64/ld-linux-x86-64.so.2 (0x0000003ff3800000)
跑下:
-
[root@localhost c]# ./test
-
main_start
-
t2_run
-
t1_run
-
libso_test_foo
-
[root@localhost c]#
果然退出来了,虽然在main中结尾 是有个while(1),但是exit了,干掉了整个进程。
参考:
http://www.cnblogs.com/vamei/archive/2013/04/04/2998850.html
http://www.cppblog.com/mydriverc/archive/2012/06/16/33163.html
另有一本关于thread的书,洋人写的真的很赞
阅读(2256) | 评论(0) | 转发(0) |