Linux命令【三】gcc編譯+靜態庫+動態庫+makefile+gdb調試

用C編譯器編譯源文件:gcc 源文件 -o 可執行文件名
詳細步驟:

  • gcc -E a.c -o a.i預處理器將頭文件展開,宏替換,去掉注釋
  • gcc -S a.i -o a.s編譯器將C文件變成匯編文件
  • gcc -c a.s -o a.o匯編器將會變文件變成二進制文件
  • gcc a.o -o a鏈接器進行鏈接

ESc+鏈接
如果不使用參數-o 則自動生成a.out

制定頭文件的路徑gcc a.c -I 頭文件的目錄 -o 生成可執行文件的名字在比較舊的版本上-I和頭文件目錄之間不能有空格,現版本無所謂
指定宏-D 宏名
優化-O1/O2/O3O3優化速度最高
輸出警告信息-Wall
生成調試信息-g

靜態庫

  1. 命名規則
    lib+庫的名字+.a
  2. 制作步驟
    生成對應的.o文件,直接使用參數-c得到.o文件,記得不要使用-o參數,否則將會直接生成可執行文件
    將生成的.o文件進行打包,需要使用軟件ar.o打包為.a
ar rcs 靜態庫名稱 所有的.o
  1. 發布和使用靜態庫
    打包靜態庫和頭文件,將所有的靜態庫放到lib文件夾中,將所有的頭文件放到include文件夾中,制作好靜態庫以后可以發送這兩個文件夾。
    用戶通過頭文件知道有哪些函數接口。通過直接和源文件編譯靜態庫使用。
gcc 源文件 靜態庫 -o 可執行文件 -Iinclude
gcc 源文件 -Iinclude -L lib -l 靜態庫文件名(去掉頭部lib和尾部.a) -o 可執行文件
  1. 靜態庫的優缺點
nm 靜態庫文件 //查看靜態庫

打包的最小單元為.o
優點:

  1. 庫已經打包在程序中,不需要再提供
  2. 庫的加載速度比較快
    缺點:
  3. 可執行文件會比較大
  4. 如果庫發生了改變需要重新編譯

動態庫/共享庫

  1. 命名規則
    lib+名字+.so
  2. 制作步驟
    (1) 生成與位置無關的代碼(.o)
gcc -fPIC -c *.c -Iinlcude

(2) 將.o打包成共享庫
Linux每一個運行的程序操作系統都會為其分配一個0-4G的地址空間。Linux下可執行文件格式:ELF

gcc -shared -o libname.so *.o -Iinclude 

再講lib中的.so文件和include中的頭文件發送給用戶

  1. 用戶使用
gcc main.c lib/libname.so -o main -Iinclude
gcc main.c -Iinclude -L lib -l name -o main//需要注意的是這里的name是不包含lib和后綴.so的

使用ldd查看可執行文件所依賴的所有的共享庫的名字

動態庫的使用需要動態鏈接器幫助。我們需要讓動態鏈接器找到我們自己的動態鏈接庫

正常情況下使用會出現動態庫無法找到的問題。然后就需要我們去解決。
可是我自己嘗試的時候沒有遇到這個情況。。。我也不清楚為什么,可能是現在版本的gcc已經智能地解決這個問題了。

(1)將動態庫放到系統的lib文件夾中
(2) 配置環境變量LD_LIBRARY_PATH(如果你的動態庫沒有在默認的環境變量中,會先在這個環境變量中查找)
用于臨時測試

echo $LD_LIBRARY_PATH //$從環境變量中取值  查看環境變量
export LD_LIBRARY_PATH=./lib //將當前目錄下的lib文件夾導入到環境變量中

關掉終端后失效
(3)

ls -a
vi .bashrc
在里面加上export LD_LIBRARY_PATH=動態庫目錄
重啟終端

永久
(4)工作中更加常用的方法

  • 找到動態鏈接器的配置文件
    /etc/ld.so.conf
    需要使用管理員權限

  • 將動態庫的路徑寫到配置文件中

  • 更新sudo ldconfig -v -v是提示信息

動態庫沒有加載到源文件中,而是在需要使用的位置加上了一個標記,在使用的時候才進行訪問。
優點:

  1. 執行程序很小
  2. 動態庫更新方便
    缺點:
  3. 需要將動態庫發布給用戶
  4. 加載庫的時候速度較慢

gdb 調試

  • l 默認展示包含main()的文件
  • l 文件名:行號 展示以行號為中心上下文件的內容
  • l 文件名:函數名 展示文件中的函數,輸入l繼續展示后面的內容,然后后面再直接按回車,會繼續向下展示文件,一次展示10行
  • break 行號在某一行打斷點b 行號
  • b 行號 if 條件條件斷點,條件斷點只能設置在循環內部,如果設置在邊界不會停止
  • b filename:行號在某個文件的某一行設置斷點
  • info break i b查看斷點信息
  • start gdb開始運行程序,每次運行一行,n單步調試,c繼續執行到斷點
  • s下一步,會進入函數體內部(step)
  • n下一步,不會進入函數內部
  • run直接運行到斷點,如果沒有斷點直接運行結束
  • p 變量 展示某個變量的值
  • ptype 變量 展示變量的類型
  • display 變量追蹤某個變量的值
  • undisplay 變量編號取消追蹤某個變量
  • info display 打印所有追蹤變量的信息
  • u將循環運行結束,結束循環
  • finish 跳出當前函數,需要將函數中的斷點消除
  • d 斷點編號刪除斷點(del)
  • set var 變量=x直接運行到變量為x的時候
  • quit退出gdb

makefile

makefile項目管理工具,用于管理源代碼

簡單makefile文件

  1. 命名規則
    (1) makefile
    (2) Makefile

  2. 編寫規則
    makefile 一般情況下要和.c文件在一個文件夾中,如果不在需要絕對路徑
    三要素:

目標:依賴 		//目標就是想要生成文件的名字  依賴:`.c`文件命令(必須要有Tab縮進):gcc a.c b.c c.c -o 目標
  1. 使用
    make

進階makefile文件

當一些文件修改以后需要重新編譯,為了解決這個問題:
例如:

app:main.o add.o sub.o mul.o		//終極目標,默認第一條語句是終極目標gcc main.o add.o sub.o mul.o -o app
//如果依賴中的文件沒有發現,就去下面的子目標中查找有沒有相關的規則用于生成文件
main.o:main.c gcc main.c -c
add.o:add.cgcc add.c -c
sub.o:sub.cgcc sub.c -c
mul.o:mul.cgcc mul.c -c

上面的寫法會自動查找文件是否修改,如果沒有修改就不會編譯,從而提高效率
工作原理:通過比較修改時間,目標應該比依賴的修改時間遲,如果發現目標比依賴的修改時間早則重新生成目標。

進進階makefile文件

上面的寫法有些冗余,通過變量來將寫法變得簡潔

obj=main.o add.o sub.o mul.o
target=app
$(target):$(obj)	//$取obj變量中的值gcc $^ -o $@
//模式規則
%.o:%.cgcc -c $< -o &@	

makefile中的自動變量:

  • $<規則中的第一個依賴
  • $@規則中的目標
  • $^規則中的所有依賴
  • 只能夠在規則中的命令來使用
    makefile自己維護的變量:
  • 都是大寫,例如CC,CPPFLAGS,CFLAGS,LDFLAGS

進進進階makefile文件

在makefile中的函數都是有返回值的

  • 獲取指定目錄下所有的.c文件
src=$(wildcard 所需要查找的目錄/*.c)
  • 獲取指定目錄下所有的.o文件
obj=$(patsubst ./%.c , ./%.o , $(src))		#模式匹配
  • 自動刪除以前生成的目標文件
clean:rm $(target) -f	#如果不存在也會強制刪除,不會彈出提示信息

生成文件 時候:

make clean   #會刪除目標文件,只會執行生成clean的語句

如果目錄中真的存在clean目標,則會提示目標是最新的而不會運行。

.PHONY:clean  #聲明clean為偽目標,不會與目錄中的目標進行比較

在命令前面加上-,則命令執行失敗以后也不會停下來,繼續向后執行

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

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

相關文章

用c++模擬實現一個學生成績管理系統

https://blog.csdn.net/yanxiaolx/article/details/53393437題目&#xff1a;用c模擬實現一個學生成績的信息管理系統&#xff0c;要求能添加、刪除、修改、查看和保存學生的信息等功能 源代碼如下:[cpp] view plaincopy#define _CRT_SECURE_NO_WARNINGS #include<iostr…

Linux命令【四】文件+虛擬內存+常用系統函數

File*其實是一個結構體 文件描述符FD&#xff1a;索引到對應的磁盤文件文件讀寫位置指針FP_POS&#xff0c;如果同時讀寫需要注意文件指針的位置I/O緩沖區BUFFER&#xff1a;保存內存指針&#xff0c;默認大小是8kb&#xff0c;用于減小我們對硬盤操作的次數。因為我們對硬盤的…

Python3列表

操作&#xff1a;索引、切片、加、乘、檢查成員、確定序列長度、確定最大最小元素 定義&#xff1a; 列表名 [元素]下標列表名[x] 截取:列表名[x:y] 更新&#xff1a; list[x]y 或者使用append()方法添加列表項刪除&#xff1a; del list[x]常用操作&#xff1a; 截取與…

Linux驚群效應詳解(最詳細的了吧)

https://blog.csdn.net/lyztyycode/article/details/78648798?locationNum6&fps1 linux驚群效應詳細的介紹什么是驚群&#xff0c;驚群在線程和進程中的具體表現&#xff0c;驚群的系統消耗和驚群的處理方法。1、驚群效應是什么&#xff1f;驚群效應也有人叫做雷鳴群體效應…

epoll原理詳解(最清晰)

https://blog.csdn.net/lyztyycode/article/details/79491419我只是把內容搬運過來做個記錄&#xff0c;方便自己以后回頭看。第一部分&#xff1a;select和epoll的任務關鍵詞&#xff1a;應用程序 文件句柄 用戶態 內核態 監控者要比較epoll相比較select高效在什么地方&#x…

Linux命令【五】系統函數

系統文件函數 stat函數 指針如果沒有const一般表示傳出參數&#xff0c;如果加const表示傳入參數 struct stat dev_t st_dev文件設備編號ino_t st_ino節點 inode號是唯一的&#xff0c;每個inode節點的大小一般是128字節活著256字節&#xff0c;一般文件每2KB就設置一個ino…

生產者-消費者模型的兩種實現方式

https://www.cnblogs.com/caolicangzhu/p/7086176.html本文主要來總結生產者-消費者模型的代碼實現,至于其原理,請大家自行百度. 一、基于鏈表的生產-消費模型(條件變量)我們以鏈表為例,生產者進行頭部插入,消費者進行頭部刪除,因此,先將鏈表相關操作封裝為LinkList.h,具體代碼…

Linux系統【一】CPU+MMU+fork函數創建進程

切板中的內容輸出到文件### 進程相關概念 程序&#xff1a;編譯好的二進制文件&#xff0c;在磁盤上&#xff0c;不占用系統資源&#xff08;不包括磁盤&#xff09;。&#xff08;劇本&#xff09; 進程&#xff1a;占用系統資源&#xff0c;是程序的一次運行。&#xff08;戲…

Ubuntu卸載軟件

用過使用dpkg軟件管理工具得到所有已經安裝的軟件&#xff0c;如果不清楚軟件的全名可以使用grep命令進行查找 然后再使用sudo apt-get remove --purge 軟件名卸載軟件&#xff08;--purge參數會刪除配置文件&#xff0c;刪的干凈一些&#xff09; 例如&#xff1a;

一個重要且實用的signal---SIGCHLD

https://blog.csdn.net/lyztyycode/article/details/78150805SIGCHLD(修改)因為筆者之前的文章里面有錯誤&#xff0c;今天發現&#xff0c;立馬做個修改。在下面我的一段關于sigchld信號相對于直接調用wait函數的好處時&#xff0c;我說調用wait函數要一直檢測子進程是否執行完…

數據結構實驗之鏈表七:單鏈表中重復元素的刪除

https://blog.csdn.net/blessingxry/article/details/794455111.知識點&#xff1a;逆序建立鏈表&#xff0b;節點刪除 2.題意&#xff1a;按照數據輸入的相反順序&#xff08;逆位序&#xff09;建立一個單鏈表&#xff0c;并將單鏈表中重復的元素刪除&#xff08;值相同的元素…

Python3函數和代碼復用

函數的定義 def 函數名([參數列表]):注釋函數體注意事項 函數形參不需要聲明類型&#xff0c;可以使用return語句在結束函數執行的同時返回任意類型的值&#xff0c;函數返回值類型與return語句返回表達式i的類型一致 即使該函數不需要接受任何參數&#xff0c;也必須保留一堆…

一文說盡C++賦值運算符重載函數(operator=)

http://www.cnblogs.com/zpcdbky/p/5027481.html在前面&#xff1a;關于C的賦值運算符重載函數(operator)&#xff0c;網絡以及各種教材上都有很多介紹&#xff0c;但可惜的是&#xff0c;內容大多雷同且不全面。面對這一局面&#xff0c;在下在整合各種資源及融入個人理解的基…

Python a和a[:]的區別

簡單來講a[:]是深復制&#xff0c;a是淺復制&#xff0c;相當于賦值a的話是賦值了指針&#xff0c;賦值a[:]相當于復制了a對應的那段空間 例如&#xff1a; a [1,1,1,1,1,1]for x in a:if x1:a.remove(x)print(a)運行結果&#xff1a; remove操作是移除序列中第一個x元素。…

約瑟夫環(c語言程序完整版)

https://blog.csdn.net/m_hahahaha1994/article/details/51742453約瑟夫環&#xff08;約瑟夫問題&#xff09;是一個數學的應用問題&#xff1a;已知n個人&#xff08;以編號1&#xff0c;2&#xff0c;3…n分別表示&#xff09;圍坐在一張圓桌周圍。從編號為k的人開始報數&am…

Linux系統【二】exec族函數及應用

文件描述符 文件描述符表是一個指針數組&#xff0c;文件描述符是一個整數。 文件描述符表對應的指針是一個結構體&#xff0c;名字為file_struct&#xff0c;里面保存的是已經打開文件的信息 需要注意的是父子進程之間讀時共享&#xff0c;寫時復制的原則是針對物理地址而言…

白話C++系列(27) -- RTTI:運行時類型識別

http://www.cnblogs.com/kkdd-2013/p/5601783.htmlRTTI—運行時類型識別 RTTI&#xff1a;Run-Time Type Identification。 那么RTTI如何來體現呢&#xff1f;這就要涉及到typeid和dynamic_cast這兩個知識點了。為了更好的去理解&#xff0c;那么我們就通過一個例子來說明。這個…

使用頭文件的原因和規范

原因 通過頭文件來調用庫功能。在很多場合&#xff0c;源代碼不便&#xff08;或不準&#xff09;向用戶公布&#xff0c;只 要向用戶提供頭文件和二進制的庫即可。用戶只需要按照頭文件中的接口聲明來調用庫 功能&#xff0c;而不必關心接口怎么實現的。編譯器會從庫中提取相應…

轉圈踢人問題

https://www.cnblogs.com/lanxuezaipiao/p/3339603.html 有N個人圍一圈依次報數&#xff0c;數到3的倍數的人出列&#xff0c;問當只剩一個人時他原來的位子在哪里&#xff1f; 解答&#xff1a;經典的轉圈踢人問題&#xff0c;好吧專業一點&#xff0c;約瑟夫環問題&#xff0…

Linux系統【三】回收子進程

孤兒進程 父進程先于子進程結束&#xff0c;則子進程成為孤兒進程&#xff0c;子進程的父進程成為init進程&#xff0c;則稱init進程領養孤兒進程。現在好像是用戶進程中的system進程。 僵尸進程 進程終止&#xff0c;父進程不進行回收&#xff0c;自己成殘留資源(PCB)存放在…