linux下的靜態庫與動態庫

来源:https://www.cnblogs.com/zhonglongbo/archive/2018/04/28/8967954.html
-Advertisement-
Play Games

[TOC] 靜態庫 先說說我們為什麼需要庫? 當有些代碼我們大量會在程式中使用比如(scanf,printf等)這些函數我們需要在程式中頻繁使用,於是我們就把這些代碼編譯為庫文件,在需要使用時我們直接鏈接即可。 定義: & 8195;程式在 時把靜態庫的代碼鏈接到可執行程式中,在代碼運行時不再需要靜 ...


[TOC]

靜態庫

先說說我們為什麼需要庫?
當有些代碼我們大量會在程式中使用比如(scanf,printf等)這些函數我們需要在程式中頻繁使用,於是我們就把這些代碼編譯為庫文件,在需要使用時我們直接鏈接即可。

定義:

 程式在編譯時把靜態庫的代碼鏈接到可執行程式中,在代碼運行時不再需要靜態庫。(簡單理解就是把一堆 .o 文件打包到一起,當需要用到就讓我們的程式鏈接進來)

生成及使用方法:

  這裡用加減乘除來舉例示意:

//創建所需文件
[root@localhost ku]# touch add.c add.h sub.c sub.h mul.c mul.h dev.c dev.h main.c 
[root@localhost ku]# ls
add.c  add.h  dev.c  dev.h  main.c  mul.c  mul.h  sub.c  sub.h
[root@localhost ku]# 
//編寫所有文件代碼
//add.c
#include"add.h"                                                                                                                       

int add(int x,int y)
{
    return x+y;
}
//add.h
 
#ifndef __ADD_H__
#define __ADD_H__

int add(int x,int y);                                                                                                                                       

#endif // __ADD_H__
//sub.c
#include"sub.h"
int sub(int x,int y)                                                                                                                  
{
    return x-y;
}
//sub.h
#ifndef __SUB_H__
#define __SUB_H__

int sub(int x,int y); 

#endif // __SUB_H__  
//mul.c
#include"mul.h"

int mul(int x,int y)                                                                                                                  
{
    return x*y;
}
//mul.h
#ifndef __MUL_H__
#define __MUL_H__

int mul(int x,int y); 

#endif //__MUL_H__   
//dev.c
#include"dev.h"

int dev(int x,int y)                                                                                                                  
{
    return x/y;
}
//dev.h
#ifndef __DEV_H__ 
#define __DEV_H__

int dev(int x,int y);                                                                                                                 

#endif // __DEV_H__
//main.c
#include<stdio.h>
#include"add.h"
#include"sub.h"
#include"mul.h"
#include"dev.h"

int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d + %d = %d\n",a,b,add(a,b));
    printf("%d - %d = %d\n",a,b,sub(a,b));
    printf("%d * %d = %d\n",a,b,mul(a,b));
    printf("%d / %d = %d\n",a,b,dev(a,b));                                                                                            
    return 0;
}

//編譯源文件
[root@localhost ku]# ls
add.c  add.h  dev.c  dev.h  main.c  mul.c  mul.h  sub.c  sub.h
[root@localhost ku]# gcc -c *.c //把所有.c文件生成.o文件
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  main.c  main.o  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# rm main.o -rf  //刪除多餘的.o文件
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# 
//生成靜態庫
[root@localhost ku]# ar -rc libmycal.a *.o
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  libmycal.a  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# 
//查看靜態庫
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  libmycal.a  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# ar -tv libmycal.a 
rw-r--r-- 0/0    683 Apr 26 20:46 2018 add.o
rw-r--r-- 0/0    683 Apr 26 20:46 2018 dev.o
rw-r--r-- 0/0    679 Apr 26 20:46 2018 mul.o
rw-r--r-- 0/0    687 Apr 26 20:46 2018 sub.o
[root@localhost ku]# 
//鏈接靜態庫生成可執行文件
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  libmycal.a  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# gcc main.c -L. -lmycal
[root@localhost ku]# ls
add.c  add.h  add.o  a.out  dev.c  dev.h  dev.o  libmycal.a  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# 
//運行結果
[root@localhost ku]# ls
add.c  add.h  add.o  a.out  dev.c  dev.h  dev.o  libmycal.a  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# ./a.out 
8 3
8 + 3 = 11
8 - 3 = 5
8 * 3 = 24
8 / 3 = 2
[root@localhost ku]# 

以上是整個靜態庫的生成及運用過程
總結起來就3步驟:

 首先將源文件編譯成目標文件:gcc –c 源文件
 生成靜態庫:ar –rc lib(庫名).a 目標文件
 使用靜態庫:gcc main.c -L(庫的路徑) -l(庫名)

靜態庫的優缺點

 優點:

 1. 省空間:linker只會複製你用到的objects。
 2. 打包簡單。

 缺點:

 1、如果靜態庫中有全局變數,那麼在幾個模塊中使用,將會導致全局變數有不同的值,這是非常嚴重的問題。
 2、靜態庫編譯時,不會進行鏈接檢查,所以這麼多靜態庫的問題,在生成靜態庫階段檢查不出來。
 3、幾個模塊,引用同一靜態庫,如果有一模塊沒有編譯到,會引起巨大的差異導致問題。
 4.產生大量的庫文件文件會占空間

動態庫

定義:

 程式在運行時才去鏈接動態庫的代碼,多個程式共用使用庫的代碼。
 一個與動態庫鏈接的可執行文件僅包含他用到的函數入口地址的一個表,而不是外部函數所在目標文件的機器碼。

生成及使用方法:

事常式序和上面一樣,這裡只寫出操作步驟

[root@localhost ku]# ls
add.c  add.h  dev.c  dev.h  main.c  mul.c  mul.h  sub.c  sub.h
[root@localhost ku]# gcc -c -fpic *.c
// -fpic   表示編譯為位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的所以動態載入時是通過代碼拷貝的方式來滿足不同進程的需要,而不能達到真正代碼段共用的目的。
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  main.c  main.o  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# rm main.o -rf
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# gcc -shared -o libmycal.so *.o
[root@localhost ku]# ls
add.c  add.h  add.o  dev.c  dev.h  dev.o  libmycal.so  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# gcc main.c -L. -lmycal
//-L.   表示要連接的庫在當前目錄中
[root@localhost ku]# ls
add.c  add.h  add.o  a.out  dev.c  dev.h  dev.o  libmycal.so  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
[root@localhost ku]# ./a.out 
./a.out: error while loading shared libraries: libmycal.so: cannot open shared object file: No such file or directory
[root@localhost ku]# cp libmycal.so /lib/
//把動態庫移動到系統庫文件下
[root@localhost ku]# ls
add.c  add.h  add.o  a.out  dev.c  dev.h  dev.o  libmycal.so  main.c  mul.c  mul.h  mul.o  sub.c  sub.h  sub.o
//運行結果
[root@localhost ku]# ./a.out 
8 6
8 + 6 = 14
8 - 6 = 2
8 * 6 = 48
8 / 6 = 1
//第二種方法,更改庫路徑
[root@localhost ku]# ./main 
./main: error while loading shared libraries: libmycal.so: cannot open shared object file: No such file or directory
[root@localhost ku]# vim /etc/ld.so.conf.d/mycal.conf //在創建的文件里寫上庫的路徑
//寫好路徑之後刷新緩衝區
[root@localhost ku]# ldconfig 
//運行結果
[root@localhost ku]# ./main 
8 6
8 + 6 = 14
8 - 6 = 2
8 * 6 = 48
8 / 6 = 1

動態庫優缺點:

優點:

 1 .共用記憶體
 2 .獨立升級組件(插件安裝,軟體更新)
 3.可以顯示動態載入

缺點:

 1.當系統中多個應用程式都用了一個動態鏈接庫,但是要求的版本不同,這時動態鏈接庫之間就會相互干擾。
 2.性能開銷。動態鏈接庫為了做到“共用代碼,但是不共用數據”,引入了不小的開銷,調用動態鏈接庫中的函數,需要好幾次間接記憶體訪問才能走到函數入口,全局數據也是。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.Image組件—“Source Image”,Set Native Size. 2.Image組件—“Image Type”——Sliced 編輯要放大縮小的圖片,Sprite Editor,採用九宮格切圖。 3.創建空物體(作為父物體),添加Componment—Layout—Grid Lay ...
  • .Net Core 是由NuGet包(package)組成的平臺。一起使用的多個包的集合:元包(Metapackage)package 包 (對應以前的程式集概念)Framework 框架assembly 程式集重要的NuGet包:System.Runtime 基礎包System.Collectio... ...
  • pwd與cd命令 >pwd命令是“print working directory”中每個單詞的首字母縮寫,其功能是顯示當前工作目錄的絕對路徑。在實際工作中,我們在命令行操作命令時,經常會在各個目錄路徑之間進行切換,此時可使用pwd命令快速查看當前我們所在的目錄路徑。 還有一個 $PWD 環境變數,可 ...
  • 結構體定義 根據定義可以看出以下幾點: 1. 鏈表結構是一個雙向鏈表。 2. 每個鏈表都由鏈表和鏈表項組成。 3. 鏈表結構體本身有一個迷你鏈表項,用來標記鏈表的結尾。 鏈表和鏈表項初始化 鏈表的操作 鏈表的插入會根據List Item Value進行升序排列,其他並沒有什麼特殊的地方。初始化並插入 ...
  • Ubuntu 下 vi 輸入方向鍵會變成 ABCD ,這個很煩人,這裡給出解決辦法,親測可行 ...
  • 今天在安裝 vim 的時候出現了 Package 'vim' has no installation candidate的問題 解決方法如下:# apt-get update# apt-get upgrade# apt-get install <packagename> 這樣就可以正常使用 apt- ...
  • 前言:前面有篇博客已經介紹了線程、線程的信號量和互斥鎖,請參考博客:http://www.cnblogs.com/liudw-0215/p/8966645.html,接下來將介紹線程池。 一、理解 線程池能有效的處理多個線程的併發問題,避免大量的線程因為互相強占系統資源導致阻塞現象,能夠有效的降低頻 ...
  • CentOS6關閉防火牆使用以下命令: CentOS7關閉防火牆使用以下命令: 若安裝了iptables-service,也可以使用下麵的命令: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...