Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1092193
  • 博文数量: 187
  • 博客积分: 1156
  • 博客等级: 少尉
  • 技术积分: 2163
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-16 15:01
个人简介

go!go!go!

文章分类

全部博文(187)

文章存档

2024年(1)

2023年(11)

2022年(13)

2021年(15)

2020年(38)

2019年(3)

2018年(6)

2016年(1)

2015年(16)

2014年(13)

2013年(24)

2012年(46)

分类: C/C++

2013-11-14 21:09:12

一.需求:
有一个独立可执行的程序 ,之前是被exec调用执行的,想改成线程 加载.so来执行。之前对.so不够了解,不清楚so中的exit是否会导致线程退出,进而导致整个进程退出?

二.测试:
1.首先整一个so出来。

  1. [root@localhost c]# cat libso_test.h
  2. #ifndef _LIBSO_TEST_H_
  3. #define _LIBSO_TEST_H_
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. void libso_test_foo();
  7. #endif


  1. [root@localhost c]# cat libso_test.c
  2. #include "libso_test.h"
  3. void libso_test_foo(void)
  4. {
  5.     printf("libso_test_foo\n");
  6.     exit(1);
  7. }
编译:
注意-fPIC选项。PIC指Position Independent Code。共享库要求有此选项,以便实现动态连接(dynamic linking)库文件以lib开始。共享库文件以.so为后缀。-shared表示生成一个共享库

  1. gcc libso_test.c -fPIC -shared -o libso_test.so
ok,检查下lib是否生成,是否有lib_test_foo这个函数,nm这个命令nm - list symbols from object files 很有用

  1. [root@localhost c]# ls libso_test.so
  2. libso_test.so
  3. [root@localhost c]# nm libso_test.so
  4. 00000000002006c0 a _DYNAMIC
  5. 0000000000200858 a _GLOBAL_OFFSET_TABLE_
  6. w _Jv_RegisterClasses
  7. 0000000000200698 d __CTOR_END__
  8. 0000000000200690 d __CTOR_LIST__
  9. 00000000002006a8 d __DTOR_END__
  10. 00000000002006a0 d __DTOR_LIST__
  11. 0000000000000688 r __FRAME_END__
  12. 00000000002006b0 d __JCR_END__
  13. 00000000002006b0 d __JCR_LIST__
  14. 0000000000200888 A __bss_start
  15. w __cxa_finalize@@GLIBC_2.2.5
  16. 00000000000005e0 t __do_global_ctors_aux
  17. 0000000000000510 t __do_global_dtors_aux
  18. 00000000002006b8 d __dso_handle
  19. w __gmon_start__
  20. 0000000000200888 A _edata
  21. 0000000000200898 A _end
  22. 0000000000000618 T _fini
  23. 0000000000000498 T _init
  24. 00000000000004f0 t call_gmon_start
  25. 0000000000200888 b completed.6349
  26. 0000000000200890 b dtor_idx.6351
  27. U exit@@GLIBC_2.2.5
  28. 0000000000000590 t frame_dummy
  29. 00000000000005bc T libso_test_foo
  30. U puts@@GLIBC_2.2.5
  31. [root@localhost c]#

2.再整个简单的test.c


  1. [root@localhost c]# cat test.c
  2. #include <pthread.h>
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include "libso_test.h"


  10. void *t1_run(void *arg)
  11. {
  12.     printf("t1_run\n");
  13.     libso_test_foo();
  14. };

  15. void *t2_run(void *arg)
  16. {
  17.     printf("t2_run\n");
  18. };
  19. int main(void)
  20. {
  21.     printf("main_start\n");
  22.     int ret = 0;
  23.     pthread_t t1,t2;
  24.     ret = pthread_create(&t1,NULL,t1_run,NULL);
  25.     assert(!ret);
  26.     ret = pthread_create(&t2,NULL,t2_run,NULL);
  27.     assert(!ret);
  28.     pthread_join(t1,NULL);
  29.     pthread_join(t2,NULL);
  30.     printf("main_end\n");
  31.     while(1)
  32.         ;    
  33.     return 0;
  34. }


再把这个so也编译到test中 -L指定目录,-lso_test 为了链接libso_test.so,注意-l后面不用加lib了

  1. gcc test.c -lpthread -L. -lso_test -o test

再检查下 test到底有没有把libso_test.so给链接进去,擦,not found

  1. [root@localhost c]# ldd test
  2. linux-vdso.so.1 => (0x00007fffbdfff000)
  3. libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003ff4400000)
  4. libso_test.so => not found
  5. libc.so.6 => /lib64/libc.so.6 (0x0000003ff4000000)
  6. /lib64/ld-linux-x86-64.so.2 (0x0000003ff3800000)

试着执行了下,faint....


  1. [root@localhost c]# ./test
  2. ./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了

  1. [root@localhost c]# export LD_LIBRARY_PATH=.
  2. [root@localhost c]# ldd test
  3.     linux-vdso.so.1 => (0x00007fff810f3000)
  4.     libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003ff4400000)
  5.     libso_test.so => ./libso_test.so (0x00007fc6df4c5000)
  6.     libc.so.6 => /lib64/libc.so.6 (0x0000003ff4000000)
  7.     /lib64/ld-linux-x86-64.so.2 (0x0000003ff3800000)

跑下:

  1. [root@localhost c]# ./test
  2. main_start
  3. t2_run
  4. t1_run
  5. libso_test_foo
  6. [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的书,洋人写的真的很赞


阅读(2089) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~