1冗澈、簡介
程序編譯一般需要經預處理、編譯陋葡、匯編和鏈接渗柿,在實際應用中,有些公共代碼需要反復使用脖岛,就把這些代碼編譯成為 "庫" 文件,本文 主要 描述 Linux 平臺下 庫文件的 創(chuàng)建 和 鏈接 相關操作(既然都看 這么底層的內容了颊亮,相信 也有一定的基礎柴梆,所以本文 對相關命令 也不會進行詳細解釋)
備注:
linux平臺下,靜態(tài)鏈接庫是以 .a 的后綴文件终惑,動態(tài)鏈接庫是以 .so 的后綴文件
widows平臺下绍在,靜態(tài)鏈接庫是以 .lib 的后綴文件,動態(tài)庫文件是以 .dll 的后綴文件
2雹有、庫文件
庫是寫好的 現(xiàn)有的偿渡、成熟的 一種可執(zhí)行、可以復用代碼的二進制形式(注霸奕,其本身不可執(zhí)行)溜宽,可以被操作系統(tǒng)載入內存執(zhí)行;分為 靜態(tài)鏈接庫 和 動態(tài)鏈接庫
2.1 靜態(tài)庫
2.1.1 簡介
靜態(tài)鏈接庫可以簡單看成一組目標文件.o 的集合质帅,即很多目標文件經過壓縮打包后形成的一個文件
2.1.2 原理
鏈接器將從 靜態(tài)(鏈接)庫 取得所需的代碼适揉,復制到生成的可執(zhí)行文件
2.1.3 特點
靜態(tài)庫對函數(shù)庫的鏈接是放在程序編譯時期完成
程序在運行時對函數(shù)庫再無瓜葛(因為所有相關的目標文件和牽涉到的函數(shù)庫被鏈接合成一個可執(zhí)行文件)
浪費空間和資源(因為所有相關的目標文件和牽涉到的函數(shù)庫被鏈接合成一個可執(zhí)行文件)
2.1.4 創(chuàng)建流程
備注:
linux下使用ar工具(windows下用lib.exe)將目標文件壓縮到一起嫉嘀,并且對其進行編號和索引,以便于查找和索引
2.1.5 命令規(guī)則
靜態(tài)鏈接庫的名稱 和 庫文件名稱不同但有聯(lián)系魄揉;例如剪侮,庫名稱為"static_library",那么起庫文件名為"libstatic_library.a"
2.2 動態(tài)庫
2.2.1 簡介
程序在開始運行后調用 動態(tài)(鏈接)庫(Dynamic Link Library)中的函數(shù) 才被載入
2.2.2 原理
程序編譯是并不會被連接到目標代碼中洛退,而是在程序運行時才被載入
2.2.3 特點
動態(tài)庫把對一些庫函數(shù)的鏈接載入推遲到程序運行時期
進程之間的相同動態(tài)庫實現(xiàn)共享
2.2.4 創(chuàng)建
創(chuàng)建動態(tài)庫與創(chuàng)建靜態(tài)庫不同杰标,不需要打包工具,直接使用編譯器創(chuàng)建動態(tài)庫
# gcc -fPIC -shared -o libxxx.so xx1.c xx2.c xx3.c
2.2.5 命名規(guī)則
動態(tài)鏈接庫的名稱 和 庫文件名稱不同但有聯(lián)系降铸;例如在旱,庫名稱為"dynamic_library",那么起庫文件名為"libdynamic_library.a"
3推掸、庫文件 編譯桶蝎、鏈接(實戰(zhàn)操作)
3.1 靜態(tài)庫 編譯、鏈接
3.1.1 靜態(tài)庫 源碼
# cat gcc_lib_header.h
#ifndef __GCC_LIB_HEADER_H_
#define __GCC_LIB_HEADER_H_
#include <stdio.h>
void gcc_lib_one();
void gcc_lib_two();
void gcc_lib_three();
#endif
# cat gcc_lib_first.c
/*
filename : gcc_lib_first.c
*/
#include "gcc_lib_header.h"
void gcc_lib_one(){
printf("call gcc_lib_one() function\n");
}
# cat gcc_lib_sec.c
/*
filename : gcc_lib_sec.c
*/
#include "gcc_lib_header.h"
void gcc_lib_two(){
printf("call gcc_lib_two() function\n");
}
# cat gcc_lib_third.c
/*
filename : gcc_lib_third.c
*/
#include "gcc_lib_header.h"
void gcc_lib_three(){
printf("call gcc_lib_three() function\n");
}
# cat gcc_lib_main.c
/*
filename : gcc_lib_main.c
*/
#include "gcc_lib_header.h"
int main(int argc, char *argv[])
{
gcc_lib_one();
gcc_lib_two();
gcc_lib_three();
return 0;
}
3.1.2 靜態(tài)庫 編譯
# gcc -c gcc_lib_first.c
# gcc -c gcc_lib_sec.c
# gcc -c gcc_lib_third.c
# ar cqs libstatic_gcc.a gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
3.1.3 靜態(tài)庫 鏈接
## -L ./ 等同于 -L.
# gcc -o gcc_lib_main_static gcc_lib_main.c -L. -static -l static_gcc
# ./gcc_lib_main_static
call gcc_lib_one() function
call gcc_lib_two() function
call gcc_lib_three() function
3.2 動態(tài)庫 編譯谅畅、鏈接
3.1.1 動態(tài)庫 源碼
為了便于測試比較登渣,使用 與 靜態(tài)庫編譯相同的源碼
3.1.2 動態(tài)庫 編譯
# gcc -fPIC -shared -o libdynamic_gcc.so gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
3.1.3 動態(tài)庫 鏈接
# gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L ./ -l dynamic_gcc
3.1.4 共享路徑設置(不詳細解釋)
## 共享路徑設置 :
## 1@:LD_LIBRARY_PATH 修改 這個全局變量
## 2@:修改 /etc/ld.so.conf 配置
## 本文 就 詳細描述了,直接把 生成的共享庫 cp 至 系統(tǒng)默認路徑下
# cp libdynamic_gxx.so /usr/local/lib/
## 重新讀取 庫文件信息(需root用戶執(zhí)行)
# ldconfig
備注:
如果 不設置 共享路徑 或者 共享路徑下 找不到 指定的 庫文件毡泻,系統(tǒng) 就會 提示相關的錯誤信息:"./g++_lib_main_static: error while loading shared libraries: libstatic_gcc.so: cannot open shared object file: Error 40"
3.1.5 執(zhí)行
## 查看 依賴庫胜茧,沒有問題 就執(zhí)行
# ldd gcc_lib_main_dynamic
linux-vdso.so.1 => (0x00007fff241e9000)
libdynamic_gcc.so => /usr/local/lib/libdynamic_gcc.so (0x00007fe587990000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe5875c6000)
/lib64/ld-linux-x86-64.so.2 (0x000055b1d62ea000)
# ./gcc_lib_main_dynamic
call gcc_lib_one() function
call gcc_lib_two() function
call gcc_lib_three() function
4、自定義工具(Makefile)
4.1 安裝 make
# apt-get install make
4.2 編寫 Makefile
# cat Makef
default_target : help
help :
@echo "usage : make [opt]"
@echo "\topt arguement is one of \"static_gcc仇味、dynamic_gcc\""
gcc_lib_first.o : gcc_lib_first.c gcc_lib_header.h
gcc -c gcc_lib_first.c
gcc_lib_sec.o : gcc_lib_sec.c gcc_lib_header.h
gcc -c gcc_lib_sec.c
gcc_lib_third.o : gcc_lib_third.c gcc_lib_header.h
gcc -c gcc_lib_third.c
static_gcc : gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
ar cqs /tmp/libstatic_gcc.a gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
gcc -o gcc_lib_main_static gcc_lib_main.c -L /tmp -static -l static_gcc
dynamic_gcc :
gcc -fPIC -shared -o /tmp/libdynamic_gcc.so gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L /tmp -l dynamic_gcc
cp /tmp/libdynamic_gcc.so /usr/local/lib/
ldconfig
4.3 執(zhí)行
## 創(chuàng)建 靜態(tài)庫 鏈接的 可執(zhí)行文件
# make static_gcc
ar cqs /tmp/libstatic_gcc.a gcc_lib_first.o gcc_lib_sec.o gcc_lib_third.o
gcc -o gcc_lib_main_static gcc_lib_main.c -L /tmp -static -l static_gcc
## 創(chuàng)建 動態(tài)庫 鏈接的 可執(zhí)行文件
# make dynamic_gcc
gcc -fPIC -shared -o /tmp/libdynamic_gcc.so gcc_lib_first.c gcc_lib_sec.c gcc_lib_third.c
gcc -o gcc_lib_main_dynamic gcc_lib_main.c -L /tmp -l dynamic_gcc
cp /tmp/libdynamic_gcc.so /usr/local/lib/
ldconfig
最后
針對于上面的面試題我總結出了互聯(lián)網(wǎng)公司java程序員面試涉及到的絕大部分面試題及答案做成了文檔和架構視頻資料免費分享給大家(包括Dubbo呻顽、Redis、Netty丹墨、zookeeper廊遍、Spring cloud、分布式贩挣、高并發(fā)等架構技術資料)喉前,希望能幫助到您面試前的復習且找到一個好的工作,也節(jié)省大家在網(wǎng)上搜索資料的時間來學習.
資料領取方式:
加Qq-u-n:****219--571--750王财,lingqu****往期Java高級架構資料卵迂、源碼、筆記绒净、視頻
Dubbo见咒、Redis、設計模式疯溺、Netty论颅、zookeeper、Spring cloud囱嫩、分布式恃疯、
高并發(fā)等架構技術