C標准:
C 標准主要由兩部分組成,一部分描述C的語法,另一部分描述C標准庫(描述了一些C標准函數的原型,但是不提供實現)。
C標准庫定義了一組標准頭文件,每個頭文件中包含一些相關的函數、變量、類型聲明和宏定義。
常見的C標准就是ANSI C;美國國家標准協會;
為了提高C語言的開發效率,C標准定義了一系列常用的函數,稱為C標准庫函數。
應用程序開發者可以包含這些標准函數的頭文件,來調用這些C標准函數,來開發應用,這樣就可以屏蔽平台的差異;
C運行庫:
C標准庫函數的實現留給了各個系統平台;
這個實現就是C運行時庫(C Run Time Libray) ,簡稱CRT;
C運行庫,是和平台相關的,即和操作系統相關的;
C運行庫(CRT)從某種程度上來講是C語言的程序和不同操作系統平台之間的抽象層;//接口是統一的標准,實現由各個平台自己實現;
Linux和Windows平台下的兩個主要C語言運行庫分別為
glibc(GNU C Library)和MSVCRT(Microsoft Visual C Run-time)。
值得注意的是,像線程操作這樣的功能並不是標准的C語言運行庫的一部分,
但是glibc和MSVCRT都包含了線程操作的庫函數。所以glibc和MSVCRT事實上是標准C語言運行庫的超集,
它們各自對C標准庫進行了一些擴展。
也就是說CRT實際上包含兩部分,一部分實現是基於C標准庫來的,一部分實現是根據平台自身開發的庫;
某種程度上是C運行庫是C標准庫的一個擴展庫,加了很多C標准庫所沒有的與平台相關的或者不相關的庫接口函數。
要在一個平台上支持C語言,不僅要實現符合平台的C編譯器,還要實現C標准庫,這樣的實現才算符合C標准。
glibc:
這里以linux系統為例進行討論;在Linux平台上最廣泛使用的C運行庫是glibc,其中包括C標准庫的實現,也包括所有系統函數。
幾乎所有C程序都要調用glibc的庫函數,所以glibc是Linux平台C程序運行的基礎。
GNU C:GNU C實際上是GNU C庫,又稱為glibc,即c運行庫;
最基本、最常用的C標准庫函數和系統函數在libc.so庫文件中,幾乎所有C程序的運行都依賴於libc.so
有些做數學計算的C程序依賴於libm.so,
多線程的C程序依賴於libpthread.so。
libc有時時專指libc.so這個庫文件,而說glibc時指的是glibc提供的所有庫文件。
值得注意的是,像線程操作這樣的功能並不是C標准庫的一部分(也就是說C標准沒有定義線程操作相關的函數原型);
但是glibc和MSVCRT(Windows系統下的C運行庫)都包含了線程操作的庫函數。
比如glibc有一個可選的pthread庫中的pthread_create()函數可以用來創建線程;
而MSVCRT中可以使用_beginthread()函數來創建線程。
所以glibc和MSVCRT事實上是標准C語言運行庫的超集,它們各自對C標准庫進行了一些擴展。
glibc的發布版本主要由兩部分組成,一部分是頭文件,比如stdio.h、stdlib.h等,它們往往位於/usr/include;
另外一部分則是庫的二進制文件部分。二進制部分主要的就是C語言標准庫,它有靜態和動態兩個版本。
動態的標准庫我們及在本書的前面章節中碰到過了,它位於/lib/libc.so.6;而靜態標准庫位於/usr/lib/libc.a。
事實上glibc除了C標准庫之外,還有幾個輔助程序運行的運行庫,這幾個文件可以稱得上是真正的“運行庫”。
它們就是/usr/lib/crt1.o、/usr/lib/crti.o和/usr/lib/crtn.o。
比如我們可以在不同的操作系統平台下使用fread來讀取文件,
而事實上fread在不同的操作系統平台下的實現是不同的,
但作為運行庫的使用者我們不需要關心這一點。
雖然各個平台下的C語言運行庫提供了很多功能,但很多時候它們畢竟有限,
比如用戶的權限控制、操作系統線程創建等都不是屬於標准的C語言運行庫。
於是我們不得不通過其他的辦法,諸如繞過C語言運行庫直接調用操作系統API或使用其他的庫。
這里講講GNU\GCC:
GNU軟件包列表:該系統的基本組成包括GNU編譯器套裝(GCC)、GNU的C庫(glibc)、以及GNU核心工具組(coreutils)、(GDB)。
GCC原名GNU C Compiler,后來逐漸支持更多的語言編譯(C++、Fortran、Pascal、Objective-C、Java、Ada、Go等),
所以變成了GNU Compiler Collection(GNU編譯器套裝)
GCC是GUN Compiler Collection的簡稱,是Linux系統上常用的編譯工具。GCC工具鏈軟件包括GCC、Binutils、C運行庫等。
GCC:
GCC(GNU C Compiler)是編譯工具。本文所要介紹的將C/C++語言編寫的程序轉換成為處理器能夠執行的二進制代碼的過程即由編譯器完成。
Binutils:
一組二進制程序處理工具,包括:addr2line、ar、objcopy、objdump、as、ld、ldd、readelf、size等。這一組工具是開發和調試不可缺少的工具。
addr2line:用來將程序地址轉換成其所對應的程序源文件及所對應的代碼行,也可以得到所對應的函數。
該工具將幫助調試器在調試的過程中定位對應的源代碼位置。
as:主要用於匯編。
ld:主要用於鏈接。
ar:主要用於創建靜態庫。
ldd:可以用於查看一個可執行程序依賴的共享庫。
objcopy:將一種對象文件翻譯成另一種格式,譬如將.bin轉換成.elf、或者將.elf轉換成.bin等。
objdump:主要的作用是反匯編。
readelf:顯示有關ELF文件的信息
size:列出可執行文件每個部分的尺寸和總尺寸,代碼段、數據段、總大小等
C運行庫
C語言標准僅僅定義了C標准庫函數原型,並沒有提供實現。
C語言編譯器通常需要一個C運行時庫(C Run Time Libray,CRT)的支持。C運行時庫又常簡稱為C運行庫。
與C語言類似,C++也定義了自己的標准,同時提供相關支持庫,稱為C++運行時庫。