有一个独立可执行的程序 ,之前是被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
- [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的书,洋人写的真的很赞
http://maxim.int.ru/bookshelf/PthreadsProgram/toc.html