红联Linux门户
Linux帮助

Linux的三种线程实现模型漫谈

发布时间:2014-11-21 09:37:53来源:linux网站作者:ylqmf

最近研究Mysql源代码,其基于 One thread per connection

现在我们通过对Linux下的线程模型的学习来串起一系列的知识点:


linux支持的三种线程模型:

1,linux Threads,这是linux标准的的线程库,但是与IEEE的POSIX不兼容.

2.Native POSIX Thread Library(简称NPTL,原生的POSIX线程库),这个线程库是RedHat开发的,支持clone()线程的系统调用,在REDHAT (KERNEL 2.6)Linux 默认是这个库.

3.Next Generation POSIX Thread(NGPT)由IBM开发的与标准的POSIX线程库兼容.但是IBM表示可能会在将来不会进行继续开发.


可以肯定的是NPTL要比LT给力得多哈!

你可以通过下面的命令来确定你的系统所支持的各个glic库的线程实现模型:

* 当然我们可以使用getconf命名简单的获得pthread的版本但这无法引出更多的知识点,getconf命令如下:

www@linux:/lib/x86_64-linux-gnu$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.13

我的Linux 为Ubuntu11.04,测试如下:(cat /etc/issue 可以看ubuntu的版本号)

以MYSQL数据库为列子.


知识点一:

首先我介绍怎么知道系统都有那些动态链接库,以动态链接库路径的查找顺序:

ldconfig -p 可以打印出ldconfig的缓存/etc/ld.so.cache


知识点二:
linux下动态链接库的查找顺序是:
1.LD_LIBRARY_PATH下的库
2.系统缺省库路径/lib and /usr/lib
3./etc/ld.so.conf 里指定的一系列路径。


知识点三:

线程库是在GLIBC库里实现的,文件名为libc.so.6,我机器上的版本是2.13,其实libc.so.6只是一个符号链接。用file命令查看它。  

www@linux:/lib/x86_64-linux-gnu$ file libc.so.6
libc.so.6: symbolic link to `libc-2.13.so'

我们先用ldd 查看我mysqld

www@linux:/usr/sbin$ ldd mysqld
linux-vdso.so.1 =>  (0x00007fff57bff000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa74dd8d000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fa74db75000)
libwrap.so.0 => /lib/libwrap.so.0 (0x00007fa74d969000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa74d765000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fa74d52c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa74d225000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa74cfa0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa74cc0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa74eb92000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007fa74c9f1000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa74c7db000)

可以知道我们的mysqld使用的是libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6  ,(我的Ubuntu是64位版本)。

进到该目录,查看具体的线程库名称:

www@linux:/lib/x86_64-linux-gnu$ ./libc.so.6 | grep [Tt]hreads
Native POSIX Threads Library by Ulrich Drepper et al


知识点四:

我们也可以看看我们的机器上所有的libc.so.6的版本: 用locate命令来定位

www@linux:/lib/x86_64-linux-gnu$ locate libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
/lib32/libc.so.6

lib32下的libc.so.6也是NPTL版本。我的机器上已经找不到linuxthreads版本了。呵呵,现在的Ubuntu的Linux内核早就是2.6的了。


知识点五:

什么是ABI?其实ABI就是系统调用加用户可以直接使用的ISA. 所以ABI版本和编译器以及系统库有关。

动态库(共享库,*.so)可以告知动态链接器它能够正常运行所必需的最低的操作系统的应用程序二进制接口(ABI)版本。

动态库的ELF格式里面有一个Note section

我们可以读到它,一般的readelf还不行,要先安装elfutils.

www@linux:sudo aptitude install elfutils

装好后,我们读取ELF里面的NOTE SECTION

-n 就是显示elf notes

www@linux:/lib/x86_64-linux-gnu$ eu-readelf -n libc-2.13.so

Note section [ 1] '.note.gnu.build-id' of 36 bytes at offset 0x270:
Owner  Data size  Type
GNU   20  GNU_BUILD_ID
Build ID: 73c3b573c5907f908727dd0484a7e0122c3bd6ab

Note section [ 2] '.note.ABI-tag' of 32 bytes at offset 0x294:
Owner  Data size  Type
GNU   16  VERSION
OS: Linux, ABI: 2.6.15

我们再次看到这个动态库需要OS: Linux, ABI: 2.6.15。

程序运行时,动态链接器会根据最近的动态库查找路径并依次查找。它会链接找到第一个满足最低ABI版本要求的库,或者无法找到满足最低ABI版本的库,链接失败并终止程序。

设置LD_ASSUME_KERNEL低于任何glibc动态库版本的最低要求的ABI版本,这样链接器将跳过该glibc库,并尝试找到一个比该版本更旧的线程实现的glibc库。

我们可以设置该环境变量,假定当前操作系统是一个特定的ABI /内核版本。这样可以达到跳过默认顺序链接的线实现 ,而使用特定版本库的线程实现。
$ export LD_ASSUME_KERNEL=X.Y.Z

列如:

由于Oracle 9i FOR LINUX是在标准的linux Threads下开发的,因此当在RedHat(kernel 2.6)linux上安装的时候,必须设定LD_ASSUME_KERNEL为2.4.0,以让redhat linux使用标准的linux Threads, 否则安装进度指示条一直停留在开始处,如:RHAS 4,RHEL 5.

当然这需要你机器上有这个版本的GLIBC.我机器上就没有。