【Linux】動靜態庫知識大梳理

親愛的讀者朋友們😃,此文開啟知識盛宴與思想碰撞🎉。

快來參與討論💬,點贊👍、收藏?、分享📤,共創活力社區。

????????在 Linux 系統編程中,動靜態庫是重要的組成部分,理解它們的原理、制作方法和使用技巧,對于開發者來說至關重要。


目錄

一、動靜態庫基礎概念

二、靜態庫的原理與操作

2.1 原理剖析

2.2 制作流程

2.3 使用方法及路徑問題

2.4 errno 的作用

2.5 庫的安裝

三、動態庫的原理與操作

3.1 原理與命令

3.2 動靜態庫分離實踐

3.3 動態庫加載問題

3.4 解決加載問題的方法

3.5 ncurses 庫介紹

四、動態加載的底層原理

4.1 動態庫加載機制

4.2 進程地址空間詳解

4.3 動態庫地址處理


一、動靜態庫基礎概念

????????庫是已編寫好、可復用的代碼,以二進制形式存在,能被操作系統載入內存執行,分為靜態庫和動態庫。

  • 靜態庫(.a)在程序編譯鏈接時,代碼被鏈接到可執行文件中(因此一般文件內存會更大),程序運行時不再依賴靜態庫;
  • 動態庫(.so)即 “Shared Object” 的縮寫,在程序運行時才鏈接代碼,多個程序可共享使用。

📌注意:?

  • 一個可執行程序可能用到許多的庫,這些庫運行時有的是靜態庫,有的是動態庫。我們的編譯默認使用動態鏈接庫,只有在該庫下找不到動態?.so?文件時,才會采用同名靜態庫。我們也可以使用?gcc?的?-static?選項強制設置鏈接靜態庫。
gcc -static main.c -o main_static

二、靜態庫的原理與操作

2.1 原理剖析

?

????????靜態庫的原理是將相關源文件編譯為.o 目標文件,再打包成 libXXX.a 文件。

????????當主程序的 main.c 編譯為 main.o 時,會自動與靜態庫鏈接形成可執行程序。在這個過程中,ar 命令用于生成靜態庫,如ar -rc libmymath.a add.o sub.o,其中-rc選項表示若目標靜態庫文件存在則替換,不存在則創建。

📌解釋:?

  • ar -rc libmymath.a add.o sub.o?這條命令的作用是,把?add.o?和?sub.o?這兩個目標文件添加到?libmymath.a?靜態庫中。如果?libmymath.a?庫文件不存在,就會創建一個新的;如果已經存在,就把?add.o?和?sub.o?插入到庫中,若庫中已有同名文件,會用新文件替換舊文件。而且,在創建或更新庫文件的過程中不會顯示提示信息。?

2.2 制作流程

以制作一個簡單的數學庫為例,先編寫源文件,如 mymath.c 定義數學運算函數,mymath.h 聲明函數。然后編寫 Makefile 文件,內容如下:

# 定義一個變量 lib,其值為靜態庫的文件名 libmymath.a
lib=libmymath.a# 這是一個目標規則,目標是生成靜態庫 libmymath.a
# 此規則表明,生成 libmymath.a 依賴于 mymath.o 文件
$(lib):mymath.o# 使用 ar 命令將 mymath.o 文件打包成靜態庫 libmymath.a# $@ 代表目標文件,即 libmymath.a# $^ 代表所有的依賴文件,即 mymath.oar -rc $@ $^# 這是一個目標規則,目標是生成目標文件 mymath.o
# 此規則表明,生成 mymath.o 依賴于 mymath.c 文件
mymath.o:mymath.c# 使用 gcc 編譯器將 mymath.c 文件編譯成目標文件 mymath.o# -c 選項表示只進行編譯,不進行鏈接# $^ 代表所有的依賴文件,即 mymath.cgcc -c $^# .PHONY 聲明了一些偽目標,偽目標不是真正的文件,而是一個動作
# 這里聲明了 clean 為偽目標,即使當前目錄下存在名為 clean 的文件,make 也會執行 clean 對應的命令
.PHONY:clean# 這是一個偽目標規則,用于清理生成的中間文件和靜態庫文件
# 執行 make clean 命令時,會刪除當前目錄下所有的 .o 文件和 .a 文件
clean:rm -f *.o *.a

????????執行 Makefile 文件,就能生成靜態庫。之后可將庫文件和頭文件整理到相應目錄,方便分發使用。

2.3 使用方法及路徑問題

???? 使用靜態庫時,需注意頭文件和庫文件的路徑設置若頭文件路徑未指定,gcc 默認在系統路徑(如 /usr/include)和當前目錄查找。可通過-I選項指定頭文件搜索路徑,如gcc main.c -I./lib/include?。對于庫文件,gcc 默認在系統路徑(如 /lib64、/usr/lib)和當前目錄查找,若找不到,需用-L選項指定庫路徑,如gcc main.c -L./lib/mymathlib此外,還需用-l選項指明要鏈接的庫名(去掉前綴 lib 和后綴.a),如gcc main.c -I./lib/include -L./lib/mymathlib -lmymath

  • -I: 指定頭文件搜索路徑
  • -L: 指定庫路徑
  • -l: 指定庫名
  • 測試目標文件生成后,靜態庫刪掉,程序照樣可以運行
  • 庫文件名稱和引入庫的名稱:去掉前綴?lib,去掉后綴?.so.a,如:libc.so?->?c

2.4 errno 的作用

????????庫中常提供全局變量 errno 用于指示運行時錯誤。如在數學庫的除法函數中,當除數為 0 時,可設置 errno 表示錯誤,方便調用者判斷結果正確性及獲取錯誤原因。

2.5 庫的安裝

????????庫的安裝本質上是將庫文件和頭文件放置到系統可查找的路徑下,可通過拷貝文件或建立軟連接實現。如將頭文件拷貝到 /usr/include,庫文件拷貝到 /lib64 ,之后編譯時只需用-l選項指定庫名即可。但不建議隨意將第三方庫安裝到系統路徑,以免污染系統庫。


三、動態庫的原理與操作

3.1 原理與命令

????????動態庫的制作同樣先將源文件編譯為.o 文件,但編譯時需添加-fPIC選項,用于生成位置無關碼,使庫能在虛擬內存的任意位置加載。生成動態庫使用gcc -shared -o libmymethod.so *.o命令,-shared選項告訴 gcc 生成共享庫。

📌解釋:?

  • 假設當前目錄下有?add.o?和?sub.o?兩個目標文件,執行?gcc -shared -o libmymethod.so *.o?命令后,gcc?會將?add.o?和?sub.o?鏈接成一個名為?libmymethod.so?的動態鏈接庫。

3.2 動靜態庫分離實踐

????????在實際開發中,可將動靜態庫分離管理。通過編寫 Makefile 文件,分別生成靜態庫和動態庫,如:

# 定義動態庫變量,值為動態庫文件名libmymethod.so
dy-lib=libmymethod.so
# 定義靜態庫變量,值為靜態庫文件名libmymath.a
static-lib=libmymath.a# 聲明all為偽目標,偽目標不是真正的文件,用于定義一組操作
.PHONY:all
# all目標,依賴于動態庫和靜態庫的生成,執行make或make all時會構建這兩個庫
all: $(dy-lib) $(static-lib)# 構建靜態庫libmymath.a的規則,依賴于mymath.o文件
$(static-lib):mymath.o# 使用ar工具將mymath.o打包成靜態庫libmymath.a# $@代表目標文件,即libmymath.a# $^代表所有的依賴文件,即mymath.oar -rc $@ $^# 從mymath.c生成mymath.o的規則
mymath.o:mymath.c# 使用gcc編譯器將mymath.c編譯成目標文件mymath.o# -c選項表示只編譯不鏈接gcc -c $^# 構建動態庫libmymethod.so的規則,依賴于mylog.o和myprint.o文件
$(dy-lib):mylog.o myprint.o# 使用gcc編譯器生成共享庫(動態庫)libmymethod.so# -shared選項用于生成共享庫# $@代表目標文件,即libmymethod.so# $^代表所有的依賴文件,即mylog.o和myprint.ogcc -shared -o $@ $^# 從mylog.c生成mylog.o的規則
mylog.o:mylog.c# 使用gcc編譯器將mylog.c編譯成目標文件mylog.o,并生成位置無關碼# -fPIC選項用于生成位置無關碼,使生成的目標文件可用于創建共享庫gcc -fPIC -c $^# 從myprint.c生成myprint.o的規則
myprint.o:myprint.c# 使用gcc編譯器將myprint.c編譯成目標文件myprint.o,并生成位置無關碼# -fPIC選項用于生成位置無關碼,使生成的目標文件可用于創建共享庫gcc -fPIC -c $^# 聲明clean為偽目標,用于清理生成的文件
.PHONY:clean
# clean目標,執行make clean時會刪除所有的.o、.a、.so文件以及mylib目錄
clean:rm -rf *.o *.a *.so mylib# 聲明output為偽目標,用于整理和輸出庫文件及頭文件
.PHONY:output
# output目標,執行make output時會創建mylib目錄結構,并將頭文件、靜態庫和動態庫文件復制到相應位置
output:# 創建mylib/include目錄,如果目錄已存在則不報錯mkdir -p mylib/include# 創建mylib/lib目錄,如果目錄已存在則不報錯mkdir -p mylib/lib# 將所有.h頭文件復制到mylib/include目錄cp *.h mylib/include# 將所有.a靜態庫文件復制到mylib/lib目錄cp *.a mylib/lib# 將所有.so動態庫文件復制到mylib/lib目錄cp *.so mylib/lib

????????這樣可清晰管理不同類型的庫,提高項目的可維護性。

?

3.3 動態庫加載問題

????????生成可執行程序后,運行時可能出現找不到動態庫的情況,如這是因為系統加載器在運行時找不到動態庫路徑,即使編譯時指定了庫路徑,運行時也需重新告知系統。?

3.4 解決加載問題的方法

?

  1. 解決動態庫加載問題有多種方法。可將動態庫拷貝到系統默認庫路徑(如 /usr/lib64);
  2. 也可在系統默認庫路徑建立軟連接,如sudo ln -s /home/whb/108/Lesson24/test/mylib/lib/libmymethod.so /lib64/libmymethod.so
  3. 還能將庫所在路徑添加到環境變量 LD_LIBRARY_PATH 中,但該方法在關閉 shell 后失效,若想長久生效,需將環境變量寫入系統啟動配置文件(如~/.bash_profile);
  4. 另外,可在 /etc/ld.so.conf.d 目錄下創建配置文件,添加動態庫路徑后執行 ldconfig 重新加載。

3.5 ncurses 庫介紹

?????????ncurses 是基于終端的圖形庫,可用于控制終端界面。在 CentOS 系統中,可通過sudo yum install ncurses-devel命令安裝,安裝后開發者能利用其豐富功能創建交互式終端應用程序,提升用戶體驗。


四、動態加載的底層原理

4.1 動態庫加載機制

????????當 CPU 執行代碼時,若調用庫函數,會先在共享區查找。若庫文件未加載進內存,會觸發缺頁中斷,系統將動態庫文件加載進來,并建立與頁表的映射關系。此后,程序在進程地址空間中執行。系統會管理多個動態庫的加載情況,確保程序正確運行。

?進程如何看到動態庫的:

?

?進程間如何共享庫的:

4.2 進程地址空間詳解

????????程序編譯好后,內部已有地址概念,采用平坦模式編址(0 - 4GB),此時的地址為邏輯地址,也是虛擬地址。編譯形成可執行程序時,會生成存儲各段地址的表,表頭地址即 main 函數地址,CPU 從該地址開始執行。執行過程中,CPU 讀取的指令可能包含數據或虛擬地址。若虛擬地址在頁表中無映射關系,會引發缺頁中斷,將所需內容加載進內存并建立映射。

4.3 動態庫地址處理

????????由于動態庫可能有多個,難以保證每個庫都加載到固定位置,因此采用相對編址方式。gcc 的-fPIC選項讓編譯器用偏移量對庫中函數編址,庫加載時,通過起始地址加偏移量的方式找到庫函數,實現庫在虛擬內存任意位置的加載!


????????動靜態庫的各個環節緊密相連,就像一條完整的 “生產線”,每個環節都不可或缺,共同支撐著 Linux 系統編程的高效運行🚀。

歡迎關注我👉【A charmer】?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74375.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74375.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74375.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

06-公寓租賃項目-后臺管理-公寓管理篇

尚庭公寓項目/公寓管理模塊 https://www.yuque.com/pkqzyh/qg2yge/5ba67653b51379d18df61b9c14c3e946 一、屬性管理 屬性管理頁面包含公寓和房間各種可選的屬性信息,其中包括房間的可選支付方式、房間的可選租期、房間的配套、公寓的配套等等。其所需接口如下 1.1…

Links for llama-cpp-python whl安裝包下載地址

Links for llama-cpp-python whl安裝包下載地址 Links for llama-cpp-python whl安裝包下載地址 https://github.com/abetlen/llama-cpp-python/releases

為境外組織提供企業商業秘密犯法嗎?

企業商業秘密百問百答之九十六:為境外組織提供企業商業秘密犯法嗎? 在日常的對外交流中,企業若暗中為境外的機構、組織或人員竊取、刺探、收買或非法提供商業秘密,這種行為嚴重侵犯了商業秘密權利人的合法權益,更深遠…

grep 命令詳解(通俗版)

1. 基礎概念 grep 是 Linux 下的文本搜索工具,核心功能是從文件或輸入流中篩選出包含指定關鍵詞的行。 它像“文本界的搜索引擎”,能快速定位關鍵信息,特別適合日志分析、代碼排查等場景。 2. 基礎語法 grep [選項] "搜索詞" 文件…

JSVMP逆向實戰:原理分析與破解思路詳解

引言 在當今Web安全領域,JavaScript虛擬機保護(JSVMP)技術被廣泛應用于前端代碼的保護和反爬機制中。作為前端逆向工程師,掌握JSVMP逆向技術已成為必備技能。本文將深入剖析JSVMP的工作原理,并分享實用的逆向破解思路…

【youcans論文精讀】弱監督深度檢測網絡(Weakly Supervised Deep Detection Networks)

歡迎關注『youcans論文精讀』系列 本專欄內容和資源同步到 GitHub/youcans 【youcans論文精讀】弱監督深度檢測網絡 WSDDN 0. 弱監督檢測的開山之作0.1 論文簡介0.2 WSDNN 的步驟0.3 摘要 1. 引言2. 相關工作3. 方法3.1 預訓練網絡3.2 弱監督深度檢測網絡3.3 WSDDN訓練3.4 空間…

基于Contiue來閱讀open-r1中的GRPO訓練代碼

原創 快樂王子HP 快樂王子AI說 2025年04月03日 23:54 廣東 前面安裝了vscode[1]同時也安裝了Coninue的相關插件[2],現在想用它們來閱讀一下open-r1項目的代碼[3]。 首先,從啟動訓練開始(以GRPO為例子) 第一步,使用TRL的vLLM后端…

JVM深入原理(六)(二):雙親委派機制

目錄 6.5. 類加載器-雙親委派機制 6.5.1. 雙親委派機制-作用 6.5.2. 雙親委派機制-工作流程 6.5.3. 雙親委派機制-父加載器 6.5.4. 雙親委派機制-面試題 6.5.5. 雙親委派機制-代碼主動加載一個類 6.6. 類加載器-打破雙親委派機制 6.6.1. 打破委派-ClassLoader原理 6.6.…

Linux 文件系統超詳解

一.磁盤 磁盤是計算機的主要存儲介質,它可以存儲大量二進制數據,即使斷電后也可以保證數據不會丟失。下面我們將了解磁盤的物理結構、存儲結構以及邏輯結構。 磁盤的存儲結構 1. 磁盤尋址的時候,基本單位既不是bit也不是byte,而…

2025年大模型與Transformer架構:重塑AI未來的科技革命

引言:一場關于智能的革命 想象一下,當你向一個虛擬助手提問時,它不僅能夠準確理解你的需求,還能生成一段流暢且富有邏輯的回答;或者當你上傳一張模糊的照片時,系統可以快速修復并生成高清版本——這一切的…

GO語言學習(16)Gin后端框架

目錄 ??前言 1.什么是前端?什么是后端?🌀 2.Gin框架介紹 🌷 3.Gin框架的基本使用 -Hello,World例子🌷 🌿入門示例 - Hello,World 💻補充(一些常用的網…

深入解析 Git Submodule:從基礎到高級操作指南

深入解析 Git Submodule:從基礎到高級操作指南 一、Git Submodule 是什么? git submodule 是 Git 提供的一個強大功能,允許在一個 Git 倉庫(主倉庫)中嵌入另一個獨立的 Git 倉庫(子模塊)。主倉…

電子電氣架構 --- EEA演進與芯片架構轉移

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 周末洗了一個澡,換了一身衣服,出了門卻不知道去哪兒,不知道去找誰,漫無目的走著,大概這就是成年人最深的孤獨吧! 舊人不知我近況,新人不知我過…

如何用deepseek生成流程圖

軟件準備: 在線流程圖【Flowchart Maker & Online Diagram Software】或【process on】 步驟: 1、用 【DeepSeek】生成 結構化內容(Mermaid文件) 1.1、向deepseek輸入指令:【幫我用mermaind寫出“某某”的具體…

【華為OD技術面試真題 - 技術面】- Java面試題(17)

華為OD面試真題精選 專欄:華為OD面試真題精選 目錄: 2024華為OD面試手撕代碼真題目錄以及八股文真題目錄 文章目錄 華為OD面試真題精選虛擬機分區1. **虛擬磁盤分區**2. **虛擬機的內存分區**3. **CPU分配**4. **虛擬網絡分區**5. **存儲虛擬化和分區**6. **虛擬機分區管理**…

Linux | I.MX6ULL內核及文件系統源碼結構(7)

01 類型 描述 備注 ARM 交叉編譯器 版本:4.9.4 提供軟件工具 Uboot 版本:2016.03 提供源碼 支持LCD顯示;支持網口; 支持 EMMC,NAND FLASH; 支持環境變量修改保存 Linux 內核 版本:4.1.15 提供…

0基礎入門scrapy 框架,獲取豆瓣top250存入mysql

一、基礎教程 創建項目命令 scrapy startproject mySpider --項目名稱 創建爬蟲文件 scrapy genspider itcast "itcast.cn" --自動生成 itcast.py 文件 爬蟲名稱 爬蟲網址 運行爬蟲 scrapy crawl baidu(爬蟲名) 使用終端運行太麻煩了,而且…

鴻蒙NEXT小游戲開發:猜小球

1. 引言 “猜小球”是一個經典的益智游戲,通常由一名表演者和多名參與者共同完成。表演者會將一個小球放在一個杯子下面,然后將三個杯子快速地交換位置,參與者則需要猜出最終哪個杯子下面有小球。本文將介紹如何使用HarmonyOS NEXT技術&…

網絡購物謹慎使用手機免密支付功能

在數字經濟蓬勃發展的當下,“免密支付”成為許多人消費時的首選支付方式。 “免密支付”的存在有其合理性。在快節奏的現代生活中,時間愈發珍貴,每節省一秒都可能帶來更高的效率。以日常通勤為例,上班族乘坐交通工具時&#xff0c…

記錄 | Android getWindow().getDecorView().setSystemUiVisibility(...)設置狀態欄屬性

純純的一邊開發一邊學習,是小白是菜鳥,單純的記錄和學習,大神勿噴,理解有錯望指正~ getWindow().getDecorView().setSystemUiVisibility(…) 該方法用于控制系統 UI(如狀態欄、導航欄)的可見性…