http://blog.csdn.net/yusiguyuan/article/details/23181327
Linux系統調用這部分經常出現兩個詞:libc庫和封裝函數,不知道你是否清楚它們的含義?
libc
libc是Standard C library的簡稱,它是符合ANSI C標准的一個標准函數庫。libc庫提供C語言中所使用的宏,類型定義,字符串操作函數,數學計算函數以及輸入輸出函數等。正如ANSI C是C語言的標准一樣,libc只是一種函數庫標准,每個操作系統都會按照該標准對標准庫進行具體實現。通常我們所說的libc是特指某個操作系統的標准庫,比如我們在Linux操作系統下所說的libc即glibc。glibc是類Unix操作系統中使用最廣泛的libc庫,它的全稱是GNU C Library。
類Unix操作系統通常將libc庫作為操作系統的一部分,它被視為操作系統與用戶程序之間的接口。libc庫不僅實現標准C語言中的函數,而且也包含自己所屬的函數接口。比如在glibc庫中,既包含標准C中的fopen(),又包含類Unix系統中的open()。在類Unix操作系統中,如果缺失了標准庫,那么整個操作系統將不能正常運轉。
與類Unix操作系統不同的是,Windows系統並不將libc庫作為整個核心操作系統的一部分。通常每個編譯器都附屬自己的libc庫,這些libc既可以靜態編譯到程序中,又可以動態編譯到程序中。也就是說應用程序依賴編譯器而不是操作系統。
封裝函數
在Linux系統中,glibc庫中包含許多API,大多數API都對應一個系統調用,比如應用程序中使用的接口open()就對應同名的系統調用open()。在glibc庫中通過封裝例程(Wrapper Routine)將API和系統調用關聯起來。API是頭文件中所定義的函數接口,而位於glibc中的封裝例程則是對該API對應功能的具體實現。事實上,我們知道接口open()所要完成的功能是通過系統調用open()完成的,因此封裝例程要做的工作就是先將接口open()中的參數復制到相應寄存器中,然后引發一個異常,從而系統進入內核去執行sys_open(),最后當系統調用執行完畢后,封裝例程還要將錯誤碼返回到應用程序中。
需要注意的是,函數庫中的API和系統調用並沒有一一對應的關系。應用程序借助系統調用可以獲得內核所提供的服務,像字符串操作這樣的函數並不需要借助內核來實現,因此也就不必與某個系統調用關聯。
不過,我們並不是必須通過封裝例程才能使用系統調用,syscall()和_syscallx()兩個函數可以直接調用系統調用。具體使用方法man手冊中已經說明的很清楚了。
glibc和libc都是Linux下的C函數庫,那么到底有什么區別呢?
見到Linux下好多的庫函數,曾經令我困惑,其實他們是有章可循的。
libc是Linux下的ANSI C的函數庫;
glibc是Linux下的GUN C函數庫;
ANSI C和GNU C有什么區別呢?
ANSI C是基本的C語言函數庫,包含了C語言最基本的庫函數。這個庫可以根據 頭文件划分為 15 個部分,其中包括:字符類型 (<ctype.h>)、錯誤碼 (<errno.h>)、 浮點常數 (<float.h>)、數學常數 (<math.h>)、標准定義 (<stddef.h>)、 標准 I/O (<stdio.h>)、工具函數 (<stdlib.h>)、字符串操作 (<string.h>)、 時間和日期 (<time.h>)、可變參數表 (<stdarg.h>)、信號 (<signal.h>)、 非局部跳轉 (<setjmp.h>)、本地信息 (<local.h>)、程序斷言 (<assert.h>) 等等。這在其他的C語言的IDE中都是有的。
而GNU C函數庫是一種類似於第三方插件的東西,由於Linux是用C語言寫的,所以Linux的一些操作是用C語言實現的,所以GNU組織開發了一個C語言的庫 用於我們更好的利用C語言開發基於Linux操作系統的程序。其實我們可以把它理解為類似於Qt是一個C++的第三方函數庫一樣。
從程序可移植性考慮,如果兩函數都可完成一種功能,選運行時庫函數好,因為各個 C 編譯器的生產商對標准C Run-time library提供了統一的支持.
1)運行時庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個名字就是因為你的 C 程序運行時需要這些庫中的函數.
2)C 語言是所謂的“小內核”語言,就其語言本身來說很小(不多的關鍵字,程序流程控制,數據類型等);所以,C 語言內核開發出來之后, Dennis Ritchie 和 Brian Kernighan 就用 C 本身重寫了 90% 以上的 UNIX 系統函數,並且把其中最常用的部分獨立出來,形成頭文件和對應的 LIBRARY,C run-time library 就是這樣形成的。
3)隨后,隨着 C 語言的流行,各個 C 編譯器的生產商/個體/團體都遵循老的傳統,在不同平台上都有相對應的 Standard Library,但大部分實現都是與各個平台有關的。由於各個 C 編譯器對 C 的支持和理解有很多分歧和微妙的差別,所以就有了 ANSI C;ANSI C (主觀意圖上)詳細的規定了 C 語言各個要素的具體含義和編譯器實現要求,引進了新的函數聲明方式,同時訂立了 Standard Library 的標准形式。所以C運行時庫由編譯器生產商提供。至於由其他廠商/個人/團體提供的頭文件和庫函數,應當稱為第三方 C 運行庫(Third party C run-time libraries)。
4)C run-time library里面含有初始化代碼,還有錯誤處理代碼(例如divide by zero處理)。你寫的程序可以沒有 math庫,程序照樣運行,只是不能處理復雜的數學運算,不過如果沒有了C run-time庫,main()就不會被調用,exit()也不能被響應。因為C run-time library包含了C程序運行的最基本和最常用的函數。
5)到了 C++ 世界里,有另外一個概念:Standard C++ Library,它包括了上面所說的 C run- time library 和 STL。包含 C run-time library 的原因很明顯,C++ 是 C 的超集,沒有理由再重新來一個 C ++ run-time library. VC針對C++ 加入的Standard C++ Library主要包括:LIBCP.LIB, LIBCPMT.LIB和 MSVCPRT.LIB
6)Windows環境下,VC提供的 C run-time library又分為動態運行時庫和靜態運行時庫。
動態運行時庫主要是DLL庫文件msvcrt.dll(or MSVCRTD.DLL for debug build),對應的Import library文件是MSVCRT.LIB(MSVCRTD.LIB for debug build)
靜態運行時庫(release版)對應的主要文件是:
LIBC.LIB (Single thread static library, retail version)
LIBCMT.LIB (Multithread static library, retail version)
msvcrt.dll提供幾千個C函數,即使是像printf這么低級的函數都在msvcrt.dll里。其實你的程序運行時,很大一部分時間時在這些運行庫里運行。在你的程序(release版)被編譯時,VC會根據你的編譯選項(單線程、多線程或DLL)自動將相應的運行時庫文件 (libc.lib,libcmt.lib或Import library msvcrt.lib)鏈接進來。
編譯時到底哪個C run-time library聯入你的程序取決於編譯選項:
/MD, /ML, /MT, /LD (Use Run-Time Library)
你可以VC中通過以下方法設置選擇哪個C run-time library聯入你的程序:
To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box. See the Use Run-Time Library drop-down box.