成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Ubuntu Linux入門到精通---GNU libc庫

系統 Linux
除了libc和libm庫,UNIX系統庫沒有其他標準的命名規(guī)范。Linux上的一些系統庫可能和UNIX平臺上庫的名稱不同,這就需要知道Linux上各庫所包含和支持的功能。

除了libc和libm庫,UNIX系統庫沒有其他標準的命名規(guī)范。Linux上的一些系統庫可能和UNIX平臺上庫的名稱不同,這就需要知道Linux上各庫所包含和支持的功能。表3-2根據所支持的功能列舉了一些Linux系統庫。

   

下面列出了GNU libc庫所包含的庫文件以及對應的描述(注釋5):

- ld.so,為使用了共享庫的可執(zhí)行程序提供的一個輔助程序;

- 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],動態(tài)鏈接接口庫。

- 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],包含為網絡域名服務器創(chuàng)建、發(fā)送、解釋網絡包的函數。

- librpcsvc.a,包含提供各種RPC服務的函數。

- librt.[a,so],包含POSIX1.b實時擴展所定義的大部分接口函數。

- libthread_db.so,包含開發(fā)多線程程序調試器的函數。

- libutil.[a,so],包含常用的UNIX工具使用的“標準”函數。

上面這些庫大多位于/usr/lib目錄,也有一些在/lib目錄下,例如libSegFault.so.

3.1.1 glibc遵循的標準

GNU glibc發(fā)布了一個描述其所遵循的標準的報告(注釋6)。該報告同時也列出了GNU libc需要改進的地方。寫作本書時,該報告顯示GNU libc通過了FIPS POSIX90、POSIX96、UNIX98、ANSI、C89/99,和ISO9899標準的頭文件一致性檢查。所有主要Linux發(fā)行版的glibc也都遵循LSB規(guī)范。

3.2 GNU科學庫

把進行高性能計算的應用程序移植到Linux上需要一個支持庫,該庫要與UNIX平臺上的科學庫非常匹配。Linux上類似的庫叫GNU科學庫(GNU Scientific Library,簡寫作GSL)。GSL是一系列數學運算例程的集合。這些例程是用C語言重新編寫的,并且給編程人員提供了一個新式的API模式---允許編程人員為各高級語言編寫包裹函數(wrapper)。這些源代碼使用的是GPL發(fā)布許可。

GNU科學庫包含了數學運算領域的很多內容。表3-3列出了GNU科學庫提供的例程。

   

這些例程的用法在GSL手冊(注釋7)中有詳盡的描述,包括函數的定義、示例程序,以及函數實現的算法所引用的論文。

3.3 共享庫

我們所移植過的大多數應用程序都使用了共享庫。然而,不同的操作系統在創(chuàng)建和命名共享庫時卻不盡相同。Linux上,共享庫可以有不同的文件擴展名,例如,共享庫可以以.so或.so.1.0結束。以.so.x.x(x為數字)結尾的共享庫叫版本化庫。第一個數字代表大版本號,第二個數字代表小版本號。有些情況下,共享庫的擴展名還可以是.so.x.x.x(x為數字)的形式,這里最后一個數字代表發(fā)布號,并且是可選的。下面給出了共享庫文件名的格式:

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

大版本號、小版本號,以及發(fā)布號的變化反映了對共享庫所作的不同類型的修改。下面是對增大大版本號、小版本號和發(fā)布號的一些指導:

- 當對共享庫提供的接口做了與以前版本不兼容的改變時,需要增大大版本號。這個大的改變意味著依賴該庫先前大版本的應用程序需要作相應修改才能使用大版本更新后的庫。

- 當共享庫增加了新的接口同時也保留了原來的接口時,增大小版本號。

- 當作了與以前兼容的修改又沒有增加新接口時,增大發(fā)布號。這通常是對一些實現做了改動以提高性能和擴展性。

要在Linux上創(chuàng)建共享庫,使用-shared編譯參數;該參數告訴GNU ld創(chuàng)建一個共享庫而不是應用程序。下面是這樣一個例子:

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

3.4 庫版本化

在共享庫和應用程序之間維護二進制級的兼容性或ABI是很重要的。共享庫的ABI是應用程序依賴的運行時接口;如果每次發(fā)布時共享庫的ABI都與以前的兼容,那么在其中某一個版本的共享庫上編譯的應用程序不需要任何改動就可以在后續(xù)版本上運行。庫版本化就是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連接器選項來創(chuàng)建符號版本化的共享庫。編譯器選項-Wl,--version-script=mapfile告訴鏈接器哪些符號要從生成的共享庫中輸出出來。每個符號分屬global(被輸出)和local(不被輸出)兩類中的一種。來看下面的例子。foo.c包含一個函數foo1,該文件用來創(chuàng)建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規(guī)范1.2及更高版本的一部分。

3.5 動態(tài)鏈接器(運行時鏈接器)

Linux動態(tài)鏈接器(/lib/ld.so.1或/lib64/ld64.so.1)查找和裝載應用程序所需的共享庫,準備應用程序的運行,然后運行應用程序。除非編譯時為ld指明-static選項,否則Linux二進制程序都是動態(tài)鏈接的。

在所有現代UNIX操作系統上,都有一些環(huán)境變量可以影響動態(tài)鏈接器的運行。例如AIX上的環(huán)境變量LIBPATH可以改變動態(tài)鏈接器的搜索路徑。以下環(huán)境變量可以影響到Linux上動態(tài)鏈接器的運行:

- LD_LIBRARY_PATH,以冒號分開的目錄列表,運行時會在這些目錄中查找需要的庫。

- LD_PRELOAD,以空格分開的庫列表,這些庫會在其他所有庫之前裝載。這常常用來有選擇的覆蓋某些共享庫中的函數。

- LD_BIND_NOW,如果該環(huán)境變量設置成非空字符串,動態(tài)鏈接器會在程序啟動時解析所有符號,而不是首次引用時才解析符號(也就是常說的“延遲綁定”)。這在使用調試器時非常有用。

- LD_TRACE_LOADED_OBJECTS,如果該環(huán)境變量設置成非空字符串,程序會列出它所依賴的共享庫,就像運行l(wèi)dd命令一樣,而不是正常的執(zhí)行。

Linux動態(tài)鏈接器采用廣度優(yōu)先(breadth first)的方式解決庫的依賴關系。也就是說,首先是可執(zhí)行程序所依賴的庫按照動態(tài)節(jié)(dynamic section)列出的順序被裝載進來,然后是“第一個被依賴的庫”所依賴的庫按照同樣的方法裝載進來,以此類推,直到所有的依賴關系都被解決。

在命令行運行下面的命令,會得到更多關于Linux動態(tài)鏈接器的信息:

(代碼)(P69第最后一行)

$ info ld.so

3.5.1 編程接口

Linux提供了一套API來動態(tài)裝載庫。下面列出了這些API:

- dlopen,打開一個庫,并為使用該庫做些準備。

- dlsym,在打開的庫中查找符號的值。

- dlclose,關閉庫。

- dlerror,返回一個描述最后一次調用dlopen、dlsym,或dlclose的錯誤信息的字符串。

C語言用戶需要包含頭文件dlfcn.h才能使用上述API。glibc還增加了兩個POSIX標準中沒有的API:

- dladdr,從函數指針解析符號名稱和所在的文件。

- dlvsym,與dlsym類似,只是多了一個版本字符串參數。

在Linux上,使用動態(tài)鏈接的應用程序需要和庫libdl.so一起鏈接,也就是使用選項-ldl。但是,編譯時不需要和動態(tài)裝載的庫一起鏈接。程序3-1是一個在Linux上使用dl*例程的簡單示例。

(代碼)(P70-73)

編譯該程序:

(代碼)(P73第5行)

$ make

運行程序:

(代碼)(P73第15行)

$ ./main

用ldd命令檢查可執(zhí)行程序:

$ ldd ./main

(代碼)(P73第19行)

可以看到,可執(zhí)行程序main沒有引用動態(tài)裝載的庫。

3.5.2 延遲重定位(Lazy Relocation)

延遲重定位/裝載是一個允許符號只在需要時才重定位的特性。這常在各UNIX系統上解析函數調用時用到。當一個和共享庫一起鏈接的應用程序幾乎不會用到該共享庫中的函數時,該特性被證明是非常有用的。這種情況下,只有庫中的函數被應用程序調用時,共享庫才會被裝載,否則不會裝載,因此會節(jié)約一些系統資源。但是如果把環(huán)境變量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()動態(tài)打開或以共享庫的形式打開時,如果_init在該庫中存在且被輸出出來,則_init函數會被調用(注釋15)。如果一個庫通過dlclose()動態(tài)關閉或因為沒有應用程序引用其符號而被卸載時,_fini函數會在庫卸載前被調用。當使用你自己的_init和_fini函數時,需要注意不要與系統啟動文件一起鏈接。可以使用GCC選項-nostartfiles做到這一點。

但是,使用上面的函數或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,一塊虛擬地址到物理地址轉換的緩沖區(qū))的未命中次數來實現的。當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的頁面。本節(jié)內容將告訴應用程序開發(fā)人員如何使用Linux內核提供的大頁面支持功能。

Linux 2.6內核包含有內建的對hugetlbpage(Linux社區(qū)稱呼大頁面的專用術語)的支持。內核配置成支持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

只有當系統中存在足夠的連續(xù)物理內存時,分配請求才會成功;只有存在足夠多的能夠轉回到正常內存池的空閑大頁面時,釋放請求才會成功。用作hugetlbpage的頁面在內核中作為保留頁面而不能用作其他用途。

應用程序開發(fā)人員有兩種方法可以使用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架構,內核為大頁面保留了一個特定的內存區(qū)域。也就是說,調用進程必須指定某一個固定的地址。但對i386,x86_64,和ppc64不需要一個固定的地址。

你也可能需要把每個共享內存段的最大大小增大到256MB。這可以用下面的命令實現:

(代碼)(P78第26行)

echo 268435456 > /proc/sys/kernel/shmmax

還需要關注的另一個限制是/proc/sys/kernel/shmall,它顯示的是系統中可以創(chuàng)建的共享內存的總頁數。

mmap system call

這種情況下,需要管理員首先掛載一個hugetlbfs類型的文件系統,然后在該掛載點上創(chuàng)建的所有文件都保存在大頁面上。

(代碼)(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文件系統上文件的屬性。

責任編輯:符甲 來源: IT專家網
相關推薦

2009-06-19 08:51:22

UbuntuLinuxGNU

2012-02-29 00:49:06

Linux學習

2009-12-15 11:18:38

GNULinux安裝vmwa

2010-02-06 15:31:18

ibmdwAndroid

2009-07-22 14:55:16

ibmdwAndroid

2016-12-08 22:39:40

Android

2017-05-09 08:48:44

機器學習

2025-02-24 10:07:10

2022-06-10 08:17:52

HashMap鏈表紅黑樹

2010-11-08 10:20:18

2024-02-26 08:52:20

Python傳遞函數參數參數傳遞類型

2022-09-02 15:11:18

開發(fā)工具

2010-02-07 10:25:11

Android

2024-09-06 17:45:55

Linux磁盤

2025-05-12 10:15:00

Linuxdiff系統

2023-10-13 08:23:05

2009-07-03 18:49:00

網吧綜合布線

2009-03-19 13:36:53

SSH安全通道遠程

2011-10-26 20:47:36

ssh 安全

2024-06-07 08:51:50

OpenPyXLPythonExcel文件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜在线| 亚洲色欧美另类 | 国产高清免费 | 91色综合| 日韩精品免费在线观看 | 亚洲国产欧美国产综合一区 | 国产 亚洲 网红 主播 | 久久久久久亚洲精品不卡 | 久久另类| 日本在线免费视频 | 亚洲一区二区三区在线免费 | av中文字幕网 | 日韩欧美在线不卡 | 精品国产黄色片 | 日本中文字幕一区 | 免费观看毛片 | 一区二区视频在线观看 | 在线看亚洲 | 黄色播放| av一区二区三区四区 | 欧美在线一区二区三区 | 成人欧美一区二区三区黑人孕妇 | 欲色av | 精品欧美一区二区三区免费观看 | 成人在线精品视频 | 久草免费在线视频 | 欧美一区 | 国产精品一区二区欧美黑人喷潮水 | 日本成人中文字幕 | 日韩精品久久 | 日韩视频在线一区 | 国产精品久久久久国产a级 欧美日本韩国一区二区 | www.久| 九九热在线视频 | 91精品久久久久久久 | 亚洲精品女优 | 欧美日韩亚洲国产 | 久久免费精品视频 | 免费在线一区二区三区 | 欧美日韩国产精品一区二区 | 日韩一二三区 |