1. 程式人生 > >嵌入式Linux-根檔案系統2_(利用交叉編譯工具鏈,構建/lib目錄)

嵌入式Linux-根檔案系統2_(利用交叉編譯工具鏈,構建/lib目錄)

光有應用程式(命令)是不夠的,因為應用程式本身需要使用C庫的庫函式,因此還必需製作for ARMC庫,並將其放置於/lib目錄。my god,要自己寫C庫的原始碼嗎?不用!還記得交叉編譯工具鏈的3個組成部分嗎?交叉編譯器、for ARMC庫和二進位制工具。我們只需要把嵌入式的C庫拷貝過來就可以了。遺憾的是:整個C庫目錄下的檔案總大小有26M。而我們根檔案系統所在分割槽不過區區16M而已,根本放不下。怎麼辦呢?

$ du -s --si/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib
26M     /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib

需要C庫目錄下所有的檔案嗎?noabsolutely no! 讓我們來分析一下glibc庫目錄下內容的組成。該目錄下的子目錄和檔案共分8類:

    1   目標檔案,如crtn.o,用於gcc連結可執行檔案

    2 libtool庫檔案(.la),在連結庫檔案時這些檔案會被用到,比如他們列出了當前庫檔案所依賴的其它庫檔案,程式執行時無需這些檔案

    3  gconv目錄,裡面是各種連結指令碼,在編譯應用程式時,他們用於指定程式的執行地址,各段的位置等

    4  靜態庫檔案(.a),例如libm.alibc.a

    5 動態庫檔案.so.so.[0-9]*

    6動態連結庫載入器ld-2.3.6.sold-linux.so.2

    7  其它目錄及檔案

    很顯然,第12347類檔案和目錄是不需要拷貝的。

   由於動態連結的應用程式本身並不含有它所呼叫的C庫函式的程式碼,因此執行時需要動態連結庫載入器來為它載入相應的

C庫檔案,所以第6類檔案是需要拷貝的。

   除此之外,第5類檔案當然要拷貝。但第5類檔案的大小也相當大。

 du -c --si *.so*

7.2M    total

需要全部拷貝嗎?非也,非也!其實,需要哪些庫完全取決於要執行的應用程式使用了哪些庫函式。如果我們只製作最簡單的系統,那麼我們只需要執行busybox這一個應用程式即可。通過執行

$arm-linux-readelf -a bin/busybox | grep 'Shared'

0x00000001(NEEDED)                    Shared library: [libcrypt.so.1]
0x00000001(NEEDED)                    Shared library: [libm.so.6]
0x00000001 (NEEDED)                    Shared library: [libc.so.6]

可知:busybox只用到了3個庫:通用C庫(libc)、數學庫(libm)、加密庫(libcrypt),因此我們只需要拷貝這3個庫的庫檔案即可。但是每個庫都有4個檔案,4個檔案都要拷貝嗎?當然不

$ls -l libcrypt[.-]*
-rwxr-xr-x 1 dennis dennis 30700 2008-01-22 05:32 libcrypt-2.3.6.so
-rw-r--r-- 1 dennis dennis 23118 2008-01-22 05:32 libcrypt.a
lrwxrwxrwx 1 dennis dennis    13 2008-12-22 15:38 libcrypt.so-> libcrypt.so.1

lrwxrwxrwx 1 dennis dennis    17 2008-12-22 15:38 libcrypt.so.1-> libcrypt-2.3.6.so


$ ls -llibm[.-]*
-rwxr-xr-x 1 dennis dennis  779096 2008-01-22 05:31 libm-2.3.6.so
-rw-r--r-- 1 dennis dennis 1134282 2008-01-22 05:32 libm.a
lrwxrwxrwx 1 dennis dennis       9 2008-12-2215:38 libm.so -> libm.so.6

lrwxrwxrwx 1 dennis dennis      13 2008-12-22 15:38libm.so.6 -> libm-2.3.6.so


$ ls -llibc[.-]*
-rwxr-xr-x 1 dennis dennis 1435660 2008-01-22 05:48 libc-2.3.6.so
-rw-r--r-- 1 dennis dennis 2768280 2008-01-22 05:31 libc.a
-rw-r--r-- 1 dennis dennis     195 2008-01-22 05:34 libc.so
lrwxrwxrwx 1 dennis dennis      13 2008-12-22 15:38libc.so.6 -> libc-2.3.6.so

4個檔案中的.a檔案是靜態庫檔案,是不需要拷貝的。另外3個檔案是:

·     實際的共享連結庫:libLIBRARY_NAME-GLIBC_VERSION.so。當然需要拷貝。

·    主修訂版本的符號連結,指向實際的共享連結庫:libLIBRARY_NAME.so.MAJOR_REVISION_VERSION,程式一旦連結了特定的連結庫,將會參用該符號連結。程式啟動時,載入器在載入程式前,會檢索該檔案。所以需要拷貝。

·   與版本無關的符號連結,指向主修訂版本的符號連線(libc.so是唯一的例外,他是一個連結命令列:libLIBRARY_NAME.so,是為編譯程式時提供一個通用條目)。這些檔案在程式被編譯時會被用到,但在程式執行時不會被用到,所以不必拷貝它。

關於共享庫的2個符號連結的作用的特別說明:

當我們使用gcc   hello.c    -o    hello    -lm編譯程式時,gcc會根據-lm的指示,加頭(lib)添尾(.so)得到libm.so,從而沿著與版本無關的符號連結(libm.so -> libm.so.6)找到libm.so.6並記錄在案(helloELF頭中),表示hello需要使用libm.so.6這個庫檔案所代表的數學庫中的庫函式。而當hello被執行的時候,動態連結庫載入器會從helloELF頭中找到libm.so.6這個記錄,然後沿著主修訂版本的符號連結(libm.so.6 -> libm-2.3.6.so)找到實際的共享連結庫libm-2.3.6.so,從而將其與hello作動態連結。可見,與版本無關的符號連結是供編譯器使用的,主修訂版本的符號連結是供動態連結庫載入器使用的,而實際的共享連結庫則是供應用程式使用的。

通過以上分析,我們只需要拷貝3個庫(每個庫各1個主修訂版本的符號連結和1個實際的共享連結庫)以及動態連結庫載入器(1個符號連結和1個實體檔案)。步驟如下:

cd  /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib:

$mkdir /work/rootfs/lib

$cp  libcrypt-* /work/rootfs/lib
$ cp -llibcrypt.so.* /work/rootfs/lib
$ cp libm-* /work/rootfs/lib
$ cp -llibm.so.* /work/rootfs/lib
$ cp libc-* /work/rootfs/lib

$ cp -llibc.so.* /work/rootfs/lib

$cp -l ld-* /work/rootfs/lib