除了libc和libm库,UNIX系统库没有其他标准的命名规范。Linux上的一些系统库可能和UNIX平台上库的名称不同,这就需要知道Linux上各库所包含和支持的功能。表3-2根据所支持的功能列举了一些Linux系统库。

除了libc和libm库,UNIX体系库没有其他规范的命名规范。Linux上的一些体系库或许和UNIX渠道上库的称号不同,这就需求知道Linux上各库所包括和支撑的功用。表3-2依据所支撑的功用列举了一些Linux体系库。

Ubuntu Linux---GNU libc库(ubuntu libc安装)  Linux GNU 第1张

下面列出了GNU libc库所包括的库文件以及对应的描绘(注释5):

  - ld.so,为运用了同享库的可履行程序供给的一个辅佐程序;

  - libBrokenLocal.[a,so],Mozilla等运用程序用以处理被损坏的locale的库文件;

  - libSegFault.so,段过错信号处理器,它企图捕获段过错信号。

  - libanl.[a,so],异步的称号查询库。

  - libbsd-compat.a,在Linux上运转BSD程序时需求的库。

  - libc.[a,so],最首要的C库(常用的C函数的调集)。

  - libcrypt.[a,so],加密库。

  - libdl.[a,so],动态链接接口库。

  - libg.a,g++运转时库。

  - libieee.a,IEEE浮点运算库。

  - libm.[a,so],数学库。

  - libmcheck.a,包括启动时运转的代码。

  - libmemusage.so,memusage用来搜集运用程序内存运用情况的库。

  - libnsl.a,网络服务库。

  - libnss_comkpat.so,libnss_dns.so, libnss_files.so, libnss_hesiod.so, libnss_nis.so, libnss_nisplus.so,NSS(Name Service Switch)库,包括解析主机名、用户名、组名、别号、服务、协议等的函数。

  - libpcprofile.so,包括一些盯梢核算代码行耗费CPU时刻的概要剖析(profiling)函数。

  - libpthread.[a,so],POSIX线程库。

  - libresolv.[a,so],包括为网络域名服务器创立、发送、解说网络包的函数。

  - librpcsvc.a,包括供给各种RPC服务的函数。

  - librt.[a,so],包括POSIX1.b实时扩展所界说的大部分接口函数。

  - libthread_db.so,包括开发多线程程序调试器的函数。

  - libutil.[a,so],包括常用的UNIX东西运用的“规范”函数。

  上面这些库大多坐落/usr/lib目录,也有一些在/lib目录下,例如libSegFault.so.

#p#

3.1.1 glibc遵从的规范

  GNU glibc发布了一个描绘其所遵从的规范的陈述(注释6)。该陈述一同也列出了GNU libc需求改善的当地。写作本书时,该陈述显现GNU libc经过了FIPS POSIX90、POSIX96、UNIX98、ANSI、C89/99,和ISO9899规范的头文件共同性查看。一切首要Linux发行版的glibc也都遵从LSB规范。

  3.2 GNU科学库

  把进行高功用核算的运用程序移植到Linux上需求一个支撑库,该库要与UNIX渠道上的科学库十分匹配。Linux上相似的库叫GNU科学库(GNU Scientific Library,简写作GSL)。GSL是一系列数学运算例程的调集。这些例程是用C言语从头编写的,而且给编程人员供给了一个新式的API办法---答应编程人员为各高档言语编写包裹函数(wrapper)。这些源代码运用的是GPL发布答应。

  GNU科学库包括了数学运算范畴的许多内容。表3-3列出了GNU科学库供给的例程。


这些例程的用法在GSL手册(注释7)中有翔实的描绘,包括函数的界说、示例程序,以及函数完成的算法所引证的论文。

  3.3 同享库

  咱们所移植过的大多数运用程序都运用了同享库。可是,不同的操作体系在创立和命名同享库时却不尽相同。Linux上,同享库能够有不同的文件扩展名,例如,同享库能够以.so或.so.1.0完毕。以.so.x.x(x为数字)结束的同享库叫版别化库。第一个数字代表大版别号,第二个数字代表小版别号。有些情况下,同享库的扩展名还能够是.so.x.x.x(x为数字)的办法,这儿最终一个数字代表发布号,而且是可选的。下面给出了同享库文件名的格局:

  (代码)p58 第11行,lib.so...

  大版别号、小版别号,以及发布号的改动反映了对同享库所作的不同类型的修正。下面是对增大大版别号、小版别号和发布号的一些辅导:

  - 当对同享库供给的接口做了与曾经版别不兼容的改动时,需求增大大版别号。这个大的改动意味着依靠该库从前大版别的运用程序需求作相应修正才干运用大版别更新后的库。

  - 当同享库添加了新的接口一同也保存了本来的接口时,增巨细版别号。

  - 当作了与曾经兼容的修正又没有添加新接口时,增大发布号。这一般是对一些完成做了改动以进步功用和扩展性。

  要在Linux上创立同享库,运用-shared编译参数;该参数告知GNU ld创立一个同享库而不是运用程序。下面是这样一个比如:

  (代码)p58 最终一行 $ gcc –o libfoo.so –shared –fpic foo.c

#p#

3.4 库版别化

  在同享库和运用程序之间保护二进制级的兼容性或ABI是很重要的。同享库的ABI是运用程序依靠的运转时接口;假如每次发布时同享库的ABI都与曾经的兼容,那么在其间某一个版别的同享库上编译的运用程序不需求任何改动就能够在后续版别上运转。库版别化便是Linux以及同期的其他操作体系完成二进制兼容性的办法。

  咱们曾经移植过的一些运用程序需求库版别化的支撑。各UNIX渠道也都完成了库版别化,但完成的办法不尽相同。Linux供给了两种不同的技能来完成库版别化:外部库版别化和符号版别化。

  3.4.1 外部库版别化

  链接过程中,链接器(ld)会查找以.so结束的同享库文件。以.so结束的库文件叫链接器称号,这是由他们在Linux上的运用办法决议的。当编译一个依靠某一同享库的运用程序时,仅仅是该同享库的soname(不是同享库的文件名)作为依靠联系被记录在运用程序的二进制代码中。运转时链接器便是运用同享库的soname来查找和装载该库的。同享库的soname只包括有大版别号(例如,libfoo.so.1)

  当修正后的同享库与曾经版别不兼容时,新的同享库有必要有一个新的外部版别称号。也便是说,该库的soname有必要改动。这些不兼容的修正包括:删去一个符号,去掉某函数的一个参数,改动了某函数的语义特点致使与曾经的界说不再共同而且与老版别二进制不兼容等等。咱们来看下面的比如。(见pdf附件 341.pdf)

   3.4.2 符号版别化

  就像前面所说到的,当对同享库所作的修正能够向前兼容时,咱们只增巨细版别号。这种修正包括添加一些新的接口一同又不改动已有的接口。可是,即便只做这种小版别的修正,也会呈现一个很重要的问题:一个在某一小版别的同享库上编译的运用程序并不一定能够在曾经小版别的库上运转。这是由于该运用程序或许运用了新添加的、曾经小版别的库中没有的接口。为了处理这个问题,引入了符号版别化。符号版别化答应同享库记录下每个小版别都新增了什么内容。

  在Linux上,GNU ld能够运用-version-script连接器选项来创立符号版别化的同享库。编译器选项-Wl,--version-script=mapfile告知链接器哪些符号要从生成的同享库中输出出来。每个符号分属global(被输出)和local(不被输出)两类中的一种。来看下面的比如。foo.c包括一个函数foo1,该文件用来创立1.1版别的同享库。(见附件 示例代码.pdf)

  能够看到,这次main只引证了版别化库的LX_1.1。

  GNU ld还答应在界说符号的源文件中把符号绑定到某一版别中,而不仅仅是在脚本文件中指定。别的,GNU ld还答应同一函数的多个版别呈现在同一个同享库中。更多详细信息,请参阅GNU ld手册(注释13)和Ulrich Drepper的文章“How to Write Shared Libraries”。

  从2.1版别开端,glibc就现已完成了符号版别化。符号版别化一同也是LSB规范1.2及更高版别的一部分。

  3.5 动态链接器(运转时链接器)

  Linux动态链接器(/lib/ld.so.1或/lib64/ld64.so.1)查找和装载运用程序所需的同享库,预备运用程序的运转,然后运转运用程序。除非编译时为ld指明-static选项,不然Linux二进制程序都是动态链接的。

  在一切现代UNIX操作体系上,都有一些环境变量能够影响动态链接器的运转。例如AIX上的环境变量LIBPATH能够改动动态链接器的查找途径。以下环境变量能够影响到Linux上动态链接器的运转:

  - LD_LIBRARY_PATH,以冒号分隔的目录列表,运转时会在这些目录中查找需求的库。

  - LD_PRELOAD,以空格分隔的库列表,这些库会在其他一切库之前装载。这常常用来有挑选的掩盖某些同享库中的函数。

  - LD_BIND_NOW,假如该环境变量设置成非空字符串,动态链接器会在程序启动时解析一切符号,而不是初次引证时才解析符号(也便是常说的“推迟绑定”)。这在运用调试器时十分有用。

  - LD_TRACE_LOADED_OBJECTS,假如该环境变量设置成非空字符串,程序会列出它所依靠的同享库,就像运转ldd指令相同,而不是正常的履行。

  Linux动态链接器选用广度优先(breadth first)的办法处理库的依靠联系。也便是说,首要是可履行程序所依靠的库依照动态节(dynamic section)列出的次序被装载进来,然后是“第一个被依靠的库”所依靠的库依照相同的办法装载进来,以此类推,直到一切的依靠联系都被处理。

  在指令行运转下面的指令,会得到更多关于Linux动态链接器的信息:

  (代码)(P69第最终一行)

  $ info ld.so

#p#

3.5.1 编程接口

  Linux供给了一套API来动态装载库。下面列出了这些API:

  - dlopen,翻开一个库,并为运用该库做些预备。

  - dlsym,在翻开的库中查找符号的值。

  - dlclose,封闭库。

  - dlerror,回来一个描绘最终一次调用dlopen、dlsym,或dlclose的过错信息的字符串。

  C言语用户需求包括头文件dlfcn.h才干运用上述API。glibc还添加了两个POSIX规范中没有的API:

  - dladdr,从函数指针解析符号称号和地点的文件。

  - dlvsym,与dlsym相似,仅仅多了一个版别字符串参数。

  在Linux上,运用动态链接的运用程序需求和库libdl.so一同链接,也便是运用选项-ldl。可是,编译时不需求和动态装载的库一同链接。程序3-1是一个在Linux上运用dl*例程的简略示例。

  (代码)(P70-73)

  编译该程序:

  (代码)(P73第5行)

  $ make

  运转程序:

  (代码)(P73第15行)

  $ ./main

  用ldd指令查看可履行程序:

  $ ldd ./main

  (代码)(P73第19行)

  能够看到,可履行程序main没有引证动态装载的库。

  3.5.2 推迟重定位(Lazy Relocation)

  推迟重定位/装载是一个答应符号只在需求时才重定位的特性。这常在各UNIX体系上解析函数调用时用到。当一个和同享库一同链接的运用程序几乎不会用到该同享库中的函数时,该特性被证明是十分有用的。这种情况下,只要库中的函数被运用程序调用时,同享库才会被装载,不然不会装载,因此会节省一些体系资源。可是假如把环境变量LD_BIND_NOW设置成一个非空值,一切的重定位操作都会在程序启动时进行。也能够在链接器指令行经过运用-z now链接器选项使推迟绑定对某个特定的同享库失效。需求留意的是,除非从头链接该同享库,不然对该同享库的这种设置会一向有用。

  3.5.3 初始化(initializing)和停止化(finalizing)函数

  有时候,曾经的代码或许用到了两个特别的函数:_init和_fini。_init和_fini函数用在装载和卸载某个模块(注释14)时别离操控该模块的结构器和析构器(或结构函数和析构函数)。他们的C言语原型如下:

  (代码)(P74第8行)

  void _init(void);

  void _fini(void);

  当一个库经过dlopen()动态翻开或以同享库的办法翻开时,假如_init在该库中存在且被输出出来,则_init函数会被调用(注释15)。假如一个库经过dlclose()动态封闭或由于没有运用程序引证其符号而被卸载时,_fini函数会在库卸载前被调用。当运用你自己的_init和_fini函数时,需求留意不要与体系启动文件一同链接。能够运用GCC选项-nostartfiles做到这一点。

#p#

可是,运用上面的函数或GCC的-nostartfiles选项并不是很好的习气,由于这或许会发生一些意外的成果。相反,库应该运用__attribute__((constructor))和__attribute__((destructor))函数特点来输出它的结构函数和析构函数。如下所示:

  (代码)(P74第21行)

  void __attribute__((constructor)) x_init(void)

  void __attribute__((destructor)) x_fini(void)

  结构函数会在dlopen()回来前或库被装载时(注释16)调用。析构函数会在这样几种情况下被调用:dlclose()回来前,或main()回来后,或装载库过程中exit()被调用时。

  3.6 体系调用

  体系调用是用户程序恳求内核为调用线程或进程供给详细服务的接口。由于UNIX渠道上的一些体系调用是与操作体系密切相关的,因此在Linux上或许不存在相似的体系调用。这种情况下,就需求在Linux上完成一个包裹函数(wrapper)。

  Linux上体系调用的列表坐落/usr/include/asm/unistd.h中。本书的附录部分还对Linux和UNIX体系(如Solaris,HP-UX等)进行了并排比较。

  3.7 大页面支撑

  大页面的运用首要是用来进步运用程序的功用,该类运用程序需求分配大块内存而且频频拜访该内存。功用的进步首要是经过削减地址转化缓冲器 (Translation Lookaside Buffer,简写作TLB,一块虚拟地址到物理地址转化的缓冲区)的未射中次数来完成的。当TLB能够映射更大的虚拟内存规模时,即可削减TLB的未射中次数。由于大部分现代的体系结构支撑多种页面巨细,上述办法也就能够完成了。例如,Intel 32位架构支撑4KB和4MB(PAE办法时为2MB)的页面;Itanium支撑多种页面巨细:4K,8K,64K,256K,1M,4M,16M和256M;SUN UltraSPARC支撑8K,64K,512K和4M的页面;64位PowerPC(ppc64)支撑4K,64K,16M和64G的页面。本节内容将告知运用程序开发人员怎么运用Linux内核供给的大页面支撑功用。

  Linux 2.6内核包括有内建的对hugetlbpage(Linux社区称号大页面的专用术语)的支撑。内核装备成支撑hugetlbpage时,指令cat /proc/meminfo的输出会显现出关于hugetlbpage的信息,如下例:

  (代码)(P75倒数第8行)

  HugePages_Total : 20

  HugePages_Free : 20

  Hugepagesize: 16384 KB

  一种类型为hugetlbfs的文件体系也应该会呈现在/proc/filesystems中。在用户空间的运用程序能够运用hugetlbpage支撑前,管理员应该先在内核中分配这些大页面。/proc/sys/vm/nr_hugepages的内容显现的是内核中当时装备的大页面的个数。假如要在体系上装备10个大页面,能够用下面的指令:

  (代码)(P76第1行)

  echo 10 > /proc/sys/vm/nr_hugepages

  只要当体系中存在满足的接连物理内存时,分配恳求才会成功;只要存在满足多的能够转回到正常内存池的闲暇大页面时,开释恳求才会成功。用作hugetlbpage的页面在内核中作为保存页面而不能用作其他用处。

  运用程序开发人员有两种办法能够运用hugetlbpage支撑:

  1. 体系V同享内存体系调用(shmget,shmat)

  2. mmap体系调用

  同一个运用程序也能够两者都运用。

  下面的示例程序中,咱们给出了怎么运用上述体系调用来取得hugetlbpage支撑。这些程序来源于/usr/src/Linux/Documentation/vm/hugetlbpage.txt。

  示例3-2中,运用程序运用体系V同享内存体系调用来请求由大页面保存的256M内存。shmget体系调用运用SHM_HUGETLB标志告知内核请求的是大页面。

  (代码)(P76-78)

  对ia86架构,内核为大页面保存了一个特定的内存区域。也便是说,调用进程有必要指定某一个固定的地址。但对i386,x86_64,和ppc64不需求一个固定的地址。

  你也或许需求把每个同享内存段的最大巨细增大到256MB。这能够用下面的指令完成:

  (代码)(P78第26行)

  echo 268435456 > /proc/sys/kernel/shmmax

  还需求重视的另一个约束是/proc/sys/kernel/shmall,它显现的是体系中能够创立的同享内存的总页数。

  mmap system call

  这种情况下,需求管理员首要挂载一个hugetlbfs类型的文件体系,然后在该挂载点上创立的一切文件都保存在大页面上。

  (代码)(P78第33行)

  mount none /mnt/huge –t hugetlbfs –o uid=1000,gid=100

  上述指令在目录/mnt/huge上挂载一个hugetlbfs类型的文件体系,并把该文件体系的根目录的一切者和组别离设置成1000和100。程序3-3给出了一个运用mmap体系调用请求由大页面保存的256MB内存的示例。

  (代码)(P79-80)

  留意,对hugetlbfs文件体系上的文件,read和write体系调用是不支撑的。一般的chown,chgrp和chmod(假如有权限的话)能够用来改动hugetlbfs文件体系上文件的特点。

【修改引荐】

  1. Linux集群根底
  2. Opera将推出Mobile Linux
  3. 玩转linux之二-驱动开发技能探析
转载请说明出处
知优网 » Ubuntu Linux---GNU libc库(ubuntu libc安装)

发表评论

您需要后才能发表评论