不懂網(wǎng)站怎么做平臺(tái)項(xiàng)鏈seo關(guān)鍵詞
目錄
Linux軟件包管理器 - yum
? Linux下安裝軟件的方式
? 認(rèn)識(shí)yum
? 查找軟件包
? 安裝軟件
? 如何實(shí)現(xiàn)本地機(jī)器和云服務(wù)器之間的文件互傳
? 卸載軟件
Linux編輯器 - vim
? vim的基本概念
? vim下各模式的切換
? vim命令模式各命令匯總
? vim底行模式各命令匯總
? vim的簡(jiǎn)單配置
Linux編譯器 - gcc/g++
? gcc/g++的作用
? gcc/g++語(yǔ)法
? 預(yù)處理
? 編譯
? 匯編
? 鏈接
? 靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)
Linux項(xiàng)目自動(dòng)化構(gòu)建工具 - make/Makefile
? make/Makefile的重要性
? 依賴(lài)關(guān)系和依賴(lài)方法
? 多文件編譯
? make原理
? 項(xiàng)目清理
Linux第一個(gè)小程序 - 進(jìn)度條
? 行緩沖區(qū)的概念
? \r和\n
? 進(jìn)度條代碼
Gitee上傳代碼
Linux調(diào)試器 - gdb
? gdb使用須知
??gdb命令匯總
Linux軟件包管理器 - yum
? Linux下安裝軟件的方式
在 Linux 系統(tǒng)中,安裝軟件的方法主要有以下三種:
-
編譯源代碼:從網(wǎng)絡(luò)上下載軟件的源代碼,然后自行編譯生成可執(zhí)行程序。這種方式適合高級(jí)用戶,可以根據(jù)需要進(jìn)行深度定制。
-
使用 rpm?包:獲取 rpm 安裝包,然后通過(guò)
rpm
命令進(jìn)行安裝。這種方法不解決軟件的依賴(lài)關(guān)系,適合安裝單個(gè)獨(dú)立的軟件包。 -
使用 yum?包管理器:通過(guò)
yum
命令進(jìn)行軟件安裝。這是最常用的方法之一,因?yàn)樗鼤?huì)自動(dòng)處理軟件的依賴(lài)關(guān)系,簡(jiǎn)化了安裝過(guò)程。
? 認(rèn)識(shí)yum
????????yum 是 Fedora、RedHat 和 CentOS 系統(tǒng)中的前端軟件包管理器。它可以自動(dòng)從指定的服務(wù)器下載并安裝 rpm 包,自動(dòng)處理依賴(lài)關(guān)系,并一次性安裝所有必需的軟件包,省去了手動(dòng)逐個(gè)下載和安裝的繁瑣過(guò)程。
注意:一個(gè)服務(wù)器同一時(shí)刻只允許一個(gè)yum進(jìn)行安裝,不能在同一時(shí)刻同時(shí)安裝多個(gè)軟件。?
????????因?yàn)閥um是從服務(wù)器上下載RPM包,所以在下載時(shí)必須聯(lián)網(wǎng),可以通過(guò)ping指令判斷當(dāng)前云服務(wù)器是否聯(lián)網(wǎng)。
? 查找軟件包
????????通過(guò) yum list 命令可以羅列出當(dāng)前一共有哪些軟件包. 由于包的數(shù)目可能非常之多, 這里我們需要使用 grep 命令只篩選出我們關(guān)注的包. 例如:
yum list | grep lrzsz
????????結(jié)果如下:
lrzsz.x86_64 0.12.20-36.el7 @base
說(shuō)明:
1)軟件包名稱(chēng):主版本號(hào).次版本號(hào).源程序發(fā)行號(hào)-軟件包的發(fā)行號(hào).主機(jī)平臺(tái).cpu架構(gòu)。
2)"x86_64"后綴表示64位系統(tǒng)的安裝包,"i686"后綴表示32位系統(tǒng)安裝包,選擇包時(shí)要和系統(tǒng)匹配。
3)"el7"表示操作系統(tǒng)發(fā)行版的版本,“el7"表示的是"centos7/redhat7”,“el6"表示"centos6/redhat6”。
4)最后一列表示的是“軟件源”的名稱(chēng),類(lèi)似于“小米應(yīng)用商店”,“華為應(yīng)用商店”這樣的概念。
? 安裝軟件
指令:?sudo?yum?install?軟件名
sudo yum install lrzsz
????????yum會(huì)自動(dòng)找到都有哪些軟件包需要下載,這時(shí)候敲“y”確認(rèn)安裝,當(dāng)出現(xiàn)“complete”字樣時(shí),說(shuō)明安裝完成。?
注意事項(xiàng):
1)安裝軟件時(shí)由于需要向系統(tǒng)目錄中寫(xiě)入內(nèi)容,一般需要sudo或者切換到root賬戶下才能完成。
2)yum安裝軟件只能一個(gè)裝完了再裝另一個(gè),正在使用yum安裝一個(gè)軟件的過(guò)程中,如果再?lài)L試用yum安裝另外一個(gè)軟件,yum會(huì)報(bào)錯(cuò)。?
? 如何實(shí)現(xiàn)本地機(jī)器和云服務(wù)器之間的文件互傳
????????既然已經(jīng)安裝了lrzsz,這里就順便說(shuō)一下lrzsz如何使用。
指令:?rz?-E
????????通過(guò)該指令可選擇需要從本地機(jī)器上傳到云服務(wù)器的文件。
指令:?sz?文件名
????????該指令可將云服務(wù)器上的文件下載到本地機(jī)器的指定文件夾。
? 卸載軟件
指令:?sudo?yum?remove?軟件名
????????yum會(huì)自動(dòng)卸載該軟件,這時(shí)候敲“y”確認(rèn)卸載,當(dāng)出現(xiàn)“complete”字樣時(shí),說(shuō)明卸載完成。
Linux編輯器 - vim
? vim的基本概念
????????Vim是一個(gè)功能強(qiáng)大的文本編輯器,特別適用于編寫(xiě)和編輯代碼。
它的核心概念包括幾種主要模式:
命令模式 (Normal mode):
????????在命令模式下,鍵盤(pán)輸入的大多數(shù)按鍵會(huì)被解釋為命令,而不是輸入字符。這時(shí)候,你可以移動(dòng)光標(biāo)、復(fù)制粘貼文本、刪除字符或行、查找替換等操作。常用的移動(dòng)命令包括
h
(左)、j
(下)、k
(上)、l
(右),以及w
(下一個(gè)單詞)、b
(前一個(gè)單詞) 等。
插入模式 (Insert mode):
????????在插入模式下,Vim類(lèi)似于普通文本編輯器,你可以直接輸入并編輯文本。進(jìn)入插入模式的常見(jiàn)方法是按下
i
鍵(在光標(biāo)當(dāng)前位置插入)、a
鍵(在光標(biāo)后插入)、o
鍵(在當(dāng)前行下插入新行并進(jìn)入插入模式)等。
底行模式 (Command-line mode):
????????底行模式允許你執(zhí)行一些底層命令,如保存文件、退出編輯器、執(zhí)行查找替換等操作。你可以通過(guò)按下
:
進(jìn)入底行模式,然后輸入相應(yīng)的命令來(lái)執(zhí)行操作。例如,:w
保存文件、:q
退出、:wq
保存并退出等。
? vim下各模式的切換
指令:?vim?文件名
russleo@virtual-machine:~/russleo$ vim test.c
????????進(jìn)入vim后默認(rèn)為命令模式(普通模式),要輸入文字需切換到插入模式。?
從命令模式切換至插入模式:
- 按下
i
:在當(dāng)前光標(biāo)處進(jìn)入插入模式,可以直接輸入文本。- 按下
a
:在當(dāng)前光標(biāo)的后一位置進(jìn)入插入模式,方便在已有文本后添加內(nèi)容。- 按下
o
:在當(dāng)前光標(biāo)所在行的下方新起一行,并進(jìn)入插入模式,適合在當(dāng)前行下方插入新內(nèi)容。從命令模式切換至底行模式:
- 輸入
Shift+;
(實(shí)際上就是輸入:
),進(jìn)入底行模式,可以執(zhí)行保存、退出等命令。從插入模式或底行模式切換至命令模式:
- 按下
Esc
鍵,即可從插入模式或底行模式返回到命令模式,這樣你可以繼續(xù)使用移動(dòng)、刪除、復(fù)制等命令操作文本。
????????這些快捷鍵和操作方法是Vim中使用頻率非常高的基礎(chǔ)操作,熟練掌握它們能夠極大提升編輯效率和流暢度。?
? vim命令模式各命令匯總
移動(dòng)光標(biāo):
k
:光標(biāo)向上移動(dòng)。j
:光標(biāo)向下移動(dòng)。h
:光標(biāo)向左移動(dòng)。l
:光標(biāo)向右移動(dòng)。$
(Shift+4):移動(dòng)到光標(biāo)所在行的行尾。^
(Shift+6):移動(dòng)到光標(biāo)所在行的行首。gg
:移動(dòng)到文本的開(kāi)頭。G
(Shift+g):移動(dòng)到文本的末尾。nG
:移動(dòng)到第n行的行首。n<Enter>
:光標(biāo)向下移動(dòng)n行。w
:跳到下一個(gè)單詞的開(kāi)頭。e
:跳到當(dāng)前或下一個(gè)單詞的結(jié)尾。b
:跳到前一個(gè)單詞的開(kāi)頭。刪除:
x
:刪除光標(biāo)所在位置的字符。nx
:刪除光標(biāo)后n個(gè)字符。X
:刪除光標(biāo)前的一個(gè)字符。nX
:刪除光標(biāo)前n個(gè)字符。dd
:刪除光標(biāo)所在行。ndd
:刪除從光標(biāo)開(kāi)始的n行。復(fù)制粘貼:
yy
:復(fù)制光標(biāo)所在行到緩沖區(qū)。nyy
:復(fù)制光標(biāo)開(kāi)始的n行到緩沖區(qū)。yw
:復(fù)制從光標(biāo)到當(dāng)前單詞結(jié)尾的字符到緩沖區(qū)。nyw
:復(fù)制光標(biāo)后的n個(gè)單詞到緩沖區(qū)。p
:粘貼緩沖區(qū)的內(nèi)容在光標(biāo)的下一行。np
:粘貼緩沖區(qū)的內(nèi)容在光標(biāo)的下一行n次。剪切:
dd
:剪切光標(biāo)所在行。ndd
:剪切從光標(biāo)開(kāi)始的n行。p
:粘貼剪切的內(nèi)容在光標(biāo)的下一行。np
:粘貼剪切的內(nèi)容在光標(biāo)的下一行n次。撤銷(xiāo)和恢復(fù):
u
:撤銷(xiāo)最后的操作。Ctrl+r
:恢復(fù)上一步撤銷(xiāo)的操作。大小寫(xiě)切換:
~
(Shift+`):切換光標(biāo)所在位置字符的大小寫(xiě)。n~
:切換光標(biāo)后n個(gè)字符的大小寫(xiě)。替換:
r
:替換光標(biāo)所在位置的字符。R
:替換從光標(biāo)位置開(kāi)始的字符,直到按下Esc
鍵。更改:
cw
:刪除從光標(biāo)到當(dāng)前單詞結(jié)尾的字符,并進(jìn)入插入模式。cnw
:刪除光標(biāo)后的n個(gè)單詞,并進(jìn)入插入模式。翻頁(yè):
Ctrl+b
:向上翻一頁(yè)。Ctrl+f
:向下翻一頁(yè)。Ctrl+u
:向上翻半頁(yè)。Ctrl+d
:向下翻半頁(yè)。
? vim底行模式各命令匯總
????????在使用底行模式之前,記住先按「Esc」鍵確定你已經(jīng)處于命令模式,再按「:」即可進(jìn)入底行模式。
行號(hào)設(shè)置:
set nu
:顯示行號(hào)。set nonu
:取消顯示行號(hào)。保存退出:
w
:保存文件。q
:退出 Vim。如果有未保存的修改,會(huì)提示保存或放棄修改。q!
:強(qiáng)制退出 Vim,丟棄所有修改。wq
:保存并退出 Vim。分屏指令:
vs 文件名
:在垂直方向上分屏打開(kāi)指定文件。Ctrl+w w
:在多個(gè)分屏之間切換光標(biāo)焦點(diǎn)。執(zhí)行指令:
!指令
:在不退出 Vim 的情況下執(zhí)行 Linux 指令。例如,可以使用:!ls
查看當(dāng)前目錄的內(nèi)容,或者:!make
編譯當(dāng)前代碼。
? vim的簡(jiǎn)單配置
關(guān)于Vim配置文件的位置和作用范圍如下:
-
系統(tǒng)級(jí)配置文件:位于
/etc/vimrc
,這是系統(tǒng)中公共的配置文件,對(duì)所有用戶都有效。系統(tǒng)管理員可以在這里設(shè)置全局的 Vim 配置選項(xiàng),影響所有用戶的 Vim 使用體驗(yàn)。 -
用戶級(jí)配置文件:位于每個(gè)用戶的主目錄下,路徑為
~/.vimrc
。例如,用戶xxx
的私有配置文件路徑為/home/xxx/.vimrc
。這是用戶私有的配置文件,只對(duì)該用戶有效。用戶可以在這里設(shè)置個(gè)性化的 Vim 配置選項(xiàng),如顯示行號(hào)、設(shè)置鍵盤(pán)映射、定義命令別名等。
????????vim的配置比較復(fù)雜,某些vim配置還需要使用插件,建議不要自己一個(gè)個(gè)去配置。比較簡(jiǎn)單的方法是直接執(zhí)行以下指令(想在哪個(gè)用戶下讓vim配置生效,就在哪個(gè)用戶下執(zhí)行該指令,不推薦直接在root下執(zhí)行):
? ? ? ? 在CSDN上有很多關(guān)于vim配置的文章,配置完成后,像什么自動(dòng)補(bǔ)全、行號(hào)顯示以及自動(dòng)縮進(jìn)什么的就都有了。?
Linux編譯器 - gcc/g++
? gcc/g++的作用
????????gcc和g++分別是GNU的C和C++的編譯器。
gcc和g++在執(zhí)行編譯的時(shí)候一般有以下四個(gè)步驟:
預(yù)處理階段:這是編譯過(guò)程的第一步,預(yù)處理器負(fù)責(zé)展開(kāi)所有的頭文件,移除注釋,進(jìn)行宏定義的替換,并根據(jù)預(yù)處理指令(如
#ifdef
、#ifndef
等)執(zhí)行條件編譯。這一階段,源代碼被調(diào)整為更適于編譯的形式。編譯階段:在預(yù)處理完成后,編譯器開(kāi)始工作,將經(jīng)過(guò)預(yù)處理的C或C++代碼翻譯成匯編語(yǔ)言。這一過(guò)程涉及到語(yǔ)法分析、語(yǔ)義分析以及優(yōu)化等復(fù)雜操作,確保生成的匯編代碼既符合規(guī)范又高效。
匯編階段:接下來(lái),匯編器接手,將上一步生成的匯編語(yǔ)言代碼轉(zhuǎn)換成機(jī)器能理解的二進(jìn)制目標(biāo)代碼。這些目標(biāo)代碼文件通常以
.o
或.obj
為擴(kuò)展名,它們是下一步鏈接過(guò)程的基本單位。鏈接階段:最后,鏈接器將所有相關(guān)的二進(jìn)制目標(biāo)代碼文件連接在一起,解決外部引用,生成最終的可執(zhí)行程序或庫(kù)文件。這一過(guò)程中,鏈接器還會(huì)處理靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)的鏈接,確保程序運(yùn)行時(shí)能夠訪問(wèn)到所需的全部資源。
? gcc/g++語(yǔ)法
語(yǔ)法:?gcc/g++?選項(xiàng)?文件
常用選項(xiàng):
-E:
當(dāng)使用這個(gè)選項(xiàng)時(shí),GCC/G++僅執(zhí)行預(yù)處理階段,并輸出預(yù)處理后的源代碼。通常用于檢查預(yù)處理的結(jié)果。
-S:
使用這個(gè)選項(xiàng)時(shí),GCC/G++會(huì)執(zhí)行預(yù)處理和編譯階段,但不會(huì)進(jìn)行匯編和鏈接。結(jié)果是一個(gè)匯編語(yǔ)言文件。
-c:
這個(gè)選項(xiàng)告訴編譯器僅編譯到目標(biāo)代碼(.o文件),而不進(jìn)行鏈接。
-o:
這個(gè)選項(xiàng)允許你指定輸出文件的名字。例如,gcc main.c -o myprogram
將編譯main.c
并將可執(zhí)行文件命名為myprogram
。
-static:
使用這個(gè)選項(xiàng)時(shí),GCC/G++會(huì)嘗試使用靜態(tài)庫(kù)進(jìn)行鏈接,而不是共享庫(kù)。這會(huì)導(dǎo)致生成的可執(zhí)行文件較大,但可能在沒(méi)有安裝相應(yīng)共享庫(kù)的系統(tǒng)上仍能運(yùn)行。
-g:
這個(gè)選項(xiàng)要求編譯器生成調(diào)試信息,使得生成的可執(zhí)行文件可以用調(diào)試器如 GDB 來(lái)調(diào)試。
-shared:
當(dāng)創(chuàng)建動(dòng)態(tài)鏈接庫(kù)(.so 文件)時(shí),需要使用此選項(xiàng)。它告訴編譯器生成一個(gè)共享對(duì)象。
-w:
這個(gè)選項(xiàng)抑制所有的警告信息。
-Wall:
相反于-w
,-Wall
開(kāi)啟盡可能多的警告信息,幫助開(kāi)發(fā)者發(fā)現(xiàn)潛在的問(wèn)題。
-O0
,-O1
,-O2
,-O3:
這些選項(xiàng)控制編譯器的優(yōu)化等級(jí)。-O0
表示不進(jìn)行優(yōu)化,而-O3
是最高等級(jí)的優(yōu)化,可以顯著提高程序的運(yùn)行速度,但可能會(huì)導(dǎo)致生成的代碼更難理解(對(duì)于人類(lèi)而言)。
? 預(yù)處理
russleo@VM-0-2-ubuntu:~/test$ gcc -E test.c -o test.i
- 預(yù)處理功能主要包括頭文件展開(kāi)、去注釋、宏替換、條件編譯等。
- 預(yù)處理指令是以#開(kāi)頭的代碼行。
- -E選項(xiàng)的作用是讓gcc/g++在預(yù)處理結(jié)束后停止編譯過(guò)程。
- -o選項(xiàng)是指目標(biāo)文件,“xxx.i”文件為已經(jīng)過(guò)預(yù)處理的原始程序。
? 編譯
russleo@VM-0-2-ubuntu:~/test$ gcc -S test.i -o test.s
- 在這個(gè)階段中,gcc/g++首先檢查代碼的規(guī)范性、是否有語(yǔ)法錯(cuò)誤等,以確定代碼的實(shí)際要做的工作,在檢查無(wú)誤后,將代碼翻譯成匯編語(yǔ)言。
- 用戶可以使用-S選項(xiàng)來(lái)進(jìn)行查看,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。
- -o選項(xiàng)是指目標(biāo)文件,“xxx.s”文件為已經(jīng)過(guò)翻譯的原始程序。
? 匯編
russleo@VM-0-2-ubuntu:~/test$ gcc -c test.s -o test.o
- 匯編階段是把編譯階段生成的“xxx.s”文件轉(zhuǎn)成目標(biāo)文件。
- 使用-c選項(xiàng)就可以得到匯編代碼轉(zhuǎn)化為“xxx.o”的二進(jìn)制目標(biāo)代碼了。
? 鏈接
russleo@VM-0-2-ubuntu:~/test$ gcc test.o -o test
- 在成功完成以上步驟之后,就進(jìn)入了鏈接階段。
- 鏈接的主要任務(wù)就是將生成的各個(gè)“xxx.o”文件進(jìn)行鏈接,生成可執(zhí)行文件。
- gcc/g++不帶-E、-S、-c選項(xiàng)時(shí),就默認(rèn)生成預(yù)處理、編譯、匯編、鏈接全過(guò)程后的文件。
- 若不用-o選項(xiàng)指定生成文件的文件名,則默認(rèn)生成的可執(zhí)行文件名為a.out
? 靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)
函數(shù)庫(kù)一般分為靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)兩種:
- 靜態(tài)庫(kù)是指編譯鏈接時(shí),把庫(kù)文件的代碼全部加入到可執(zhí)行文件當(dāng)中,因此生成的文件比較大,但在運(yùn)行時(shí)也就不再需要庫(kù)文件了,靜態(tài)庫(kù)一般以.a為后綴。
- 動(dòng)態(tài)庫(kù)與之相反,在編譯鏈接時(shí)并沒(méi)有把庫(kù)文件的代碼加入到可執(zhí)行文件當(dāng)中,而是在程序運(yùn)行時(shí)由鏈接文件加載庫(kù),這樣可以節(jié)省系統(tǒng)的開(kāi)銷(xiāo),動(dòng)態(tài)庫(kù)一般以.so為后綴。
動(dòng)態(tài)鏈接:
?優(yōu)點(diǎn):省空間(磁盤(pán)的空間,內(nèi)存的空間),bin體積小,加載速度快。
?缺點(diǎn):依賴(lài)動(dòng)態(tài)庫(kù),程序可移植性較差。
靜態(tài)鏈接:
?優(yōu)點(diǎn):不依賴(lài)第三方庫(kù),程序的可移植性較高。
?缺點(diǎn):浪費(fèi)空間。?
gcc和g++默認(rèn)生成的二進(jìn)制程序是動(dòng)態(tài)鏈接的,我們可以使用file指令進(jìn)行查看。
其次,我們還可以使用ldd指令查看動(dòng)態(tài)鏈接的可執(zhí)行文件所依賴(lài)的庫(kù)。
雖然gcc和g++默認(rèn)采用的是動(dòng)態(tài)鏈接,但如果我們需要使用靜態(tài)鏈接,帶上-static選項(xiàng)即可。
russleo@VM-0-2-ubuntu:~/test$ gcc test.c -o test_s -static
此時(shí)生成的可執(zhí)行文件就是靜態(tài)鏈接的了。?
????????我們可以查看源代碼相同,但鏈接方式不同而生成的兩個(gè)可執(zhí)行程序test和test_s的大小。這也證明了動(dòng)態(tài)鏈接比較節(jié)省空間,而靜態(tài)鏈接比較浪費(fèi)空間。
Linux項(xiàng)目自動(dòng)化構(gòu)建工具 - make/Makefile
? make/Makefile的重要性
????????撰寫(xiě)Makefile的能力對(duì)于大型軟件工程的管理至關(guān)重要,它不僅反映了一個(gè)開(kāi)發(fā)者對(duì)項(xiàng)目結(jié)構(gòu)和構(gòu)建流程的理解深度,還體現(xiàn)了其能否高效地處理復(fù)雜工程的能力。在大型項(xiàng)目中,源代碼文件數(shù)量龐大,根據(jù)類(lèi)型、功能或模塊被精心組織在不同的目錄下。此時(shí),Makefile就像一個(gè)指揮家,通過(guò)預(yù)定義的規(guī)則,有序地安排文件的編譯順序,甚至執(zhí)行更為復(fù)雜的任務(wù),如依賴(lài)性管理、資源清理等。
????????Makefile的核心優(yōu)勢(shì)在于實(shí)現(xiàn)“自動(dòng)化編譯”。一旦正確配置,只需簡(jiǎn)單輸入make
命令,整個(gè)工程就能自動(dòng)完成編譯,顯著提升了開(kāi)發(fā)效率,減少了人為錯(cuò)誤,使得軟件構(gòu)建過(guò)程更加穩(wěn)定可靠。此外,make
作為解釋Makefile指令的工具,已廣泛集成到各種集成開(kāi)發(fā)環(huán)境(IDE)中,如Delphi的make
,Visual C++的nmake
,以及Linux下GNU的make
,這表明Makefile已經(jīng)成為跨平臺(tái)項(xiàng)目構(gòu)建的標(biāo)準(zhǔn)實(shí)踐。
????????總之,Makefile與make
命令的結(jié)合,為軟件工程提供了一種標(biāo)準(zhǔn)化、自動(dòng)化的構(gòu)建方案,是現(xiàn)代軟件開(kāi)發(fā)中不可或缺的一部分。掌握Makefile的編寫(xiě),意味著能夠更好地管理和優(yōu)化大型項(xiàng)目的構(gòu)建流程,提高團(tuán)隊(duì)的開(kāi)發(fā)效率。
注意:make是一條命令,Makefile是一個(gè)文件
? 依賴(lài)關(guān)系和依賴(lài)方法
在使用make/Makefile前我們首先應(yīng)該理解各個(gè)文件之間的依賴(lài)關(guān)系以及它們之間的依賴(lài)方法。
依賴(lài)關(guān)系: 文件A的變更會(huì)影響到文件B,那么就稱(chēng)文件B依賴(lài)于文件A。
????????例如,test.o文件是由test.c文件通過(guò)預(yù)處理、編譯以及匯編之后生成的文件,所以test.c文件的改變會(huì)影響test.o,所以說(shuō)test.o文件依賴(lài)于test.c文件。
依賴(lài)方法: 如果文件B依賴(lài)于文件A,那么通過(guò)文件A得到文件B的方法,就是文件B依賴(lài)于文件A的依賴(lài)方法。
????????例如,test.o依賴(lài)于test.c,而test.c通過(guò)gcc -c test.c -o
test.o指令就可以得到test.o,那么test.o依賴(lài)于test.c的依賴(lài)方法就是gcc -c test.c -o test.o。
? 多文件編譯
????????在處理包含多個(gè)源文件的工程項(xiàng)目時(shí),采用多步驟的編譯策略可以顯著提升開(kāi)發(fā)效率和構(gòu)建速度。直接使用gcc
命令一次性編譯所有源文件雖然可行,但在源代碼頻繁變更的情況下,這種做法會(huì)導(dǎo)致不必要的重復(fù)工作,因?yàn)槟呐轮皇菃蝹€(gè)源文件發(fā)生改動(dòng),也需要重新編譯整個(gè)項(xiàng)目。
????????相比之下,先將每個(gè)源文件獨(dú)立編譯成目標(biāo)文件(通常為.o
格式的二進(jìn)制文件),再將這些目標(biāo)文件鏈接生成最終的可執(zhí)行程序,是一種更為高效的做法。這種方式的好處在于,當(dāng)你修改了某個(gè)源文件后,只需要重新編譯那個(gè)特定的源文件,生成新的目標(biāo)文件,然后與其它未改動(dòng)的目標(biāo)文件一起進(jìn)行鏈接,從而生成更新后的可執(zhí)行程序。這樣既節(jié)省了時(shí)間,又避免了資源的浪費(fèi)。
首先,針對(duì)每個(gè)源文件,使用
gcc
命令進(jìn)行編譯,生成相應(yīng)的目標(biāo)文件。例如:gcc -c file1.c -o file1.o gcc -c file2.c -o file2.o
?然后,將所有生成的目標(biāo)文件鏈接起來(lái),創(chuàng)建可執(zhí)行程序:
gcc file1.o file2.o -o executable
????????需要注意的是,在編譯階段,無(wú)需顯式指定頭文件路徑。編譯器會(huì)根據(jù)源文件中的#include
指令自動(dòng)查找所需的頭文件。如果頭文件使用的是標(biāo)準(zhǔn)庫(kù),通常使用尖括號(hào)<>
包含;如果是項(xiàng)目?jī)?nèi)部的自定義頭文件,則使用雙引號(hào)""
包含。編譯器會(huì)依據(jù)不同的包含方式,從系統(tǒng)庫(kù)路徑或當(dāng)前項(xiàng)目路徑查找對(duì)應(yīng)的頭文件。?
????????但是隨著源文件個(gè)數(shù)的增加,我們每次重新生成可執(zhí)行程序時(shí),所需輸入的gcc指令的長(zhǎng)度與個(gè)數(shù)也會(huì)隨之增加。這時(shí)我們就需要使用make和Makefile了,這將大大減少我們的工作量。
????????步驟1: 在源文件所在目錄下創(chuàng)建一個(gè)名為Makefile/makefile的文件。
????????步驟2: 編寫(xiě)Makefile文件。
????????Makefile文件最簡(jiǎn)單的編寫(xiě)格式是,先寫(xiě)出文件的依賴(lài)關(guān)系,然后寫(xiě)出這些文件之間的依賴(lài)方法,依次寫(xiě)下去。
????????編寫(xiě)完畢Makefile文件后保存退出,然后在命令行當(dāng)中執(zhí)行make指令便可以生成可執(zhí)行程序,以及該過(guò)程產(chǎn)生的中間產(chǎn)物。
Makefile文件的簡(jiǎn)寫(xiě)方式:
- $@:表示依賴(lài)關(guān)系中的目標(biāo)文件(冒號(hào)左側(cè))。
- $^:表示依賴(lài)關(guān)系中的依賴(lài)文件列表(冒號(hào)右側(cè)全部)。
- $<:表示依賴(lài)關(guān)系中的第一個(gè)依賴(lài)文件(冒號(hào)右側(cè)第一個(gè))。
例如以上Makefile文件可以簡(jiǎn)寫(xiě)為:
?
????????說(shuō)明:?gcc/g++攜帶-c選項(xiàng)時(shí),若不指定輸出文件的文件名,則默認(rèn)輸出文件名為xxx.o,所以這里也可以不用指定輸出文件名。?
? make原理
- make會(huì)在當(dāng)前目錄下找名字為“Makefile”或“makefile”的文件。
- 如果找到,它會(huì)找文件當(dāng)中的第一個(gè)目標(biāo)文件,在上面的例子中,它會(huì)找到mytest這個(gè)文件,并把這個(gè)文件作為最終的目標(biāo)文件。
- 如果mytest文件不存在,或是mytest所依賴(lài)的后面的test.o文件和main.o文件的文件修改時(shí)間比mytest文件新,那么它就會(huì)執(zhí)行后面的依賴(lài)方法來(lái)生成mytest文件。
- 如果mytest所依賴(lài)的test.o文件不存在,那么make會(huì)在Makefile文件中尋找目標(biāo)為test.o文件的依賴(lài)關(guān)系,如果找到則再根據(jù)其依賴(lài)方法生成test.o文件(類(lèi)似于堆棧的過(guò)程)。
- 當(dāng)然,你的test.c文件和main.c文件是存在的,于是make會(huì)生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最終的mytest文件。
- make會(huì)一層又一層地去找文件的依賴(lài)關(guān)系,直到最終編譯出第一個(gè)目標(biāo)文件。
- 在尋找的過(guò)程中,如果出現(xiàn)錯(cuò)誤,例如最后被依賴(lài)的文件找不到,那么make就會(huì)直接退出,并報(bào)錯(cuò)。
? 項(xiàng)目清理
????????在我們每次重新生成可執(zhí)行程序前,都應(yīng)該將上一次生成可執(zhí)行程序時(shí)生成的一系列文件進(jìn)行清理,但是如果我們每次都手動(dòng)執(zhí)行一系列指令進(jìn)行清理工作的話,未免有些麻煩,因?yàn)槊看吻謇頃r(shí)執(zhí)行的都是相同的清理指令,這時(shí)我們可以將項(xiàng)目清理的指令也加入到Makefile文件當(dāng)中。
????????即命令——“make clean”,以此來(lái)清除所有的目標(biāo)文件,以便重編譯。?
Linux第一個(gè)小程序 - 進(jìn)度條
? 行緩沖區(qū)的概念
????????首先,我們來(lái)感受一下行緩沖區(qū)的存在,在Linux當(dāng)中以下代碼的運(yùn)行結(jié)果是什么樣的?
????????對(duì)于此代碼,大家應(yīng)該都沒(méi)問(wèn)題,當(dāng)然是先輸出字符串hello world然后休眠3秒之后結(jié)束運(yùn)行。那么對(duì)于以下代碼呢?
????????可以看到代碼中僅僅刪除了字符串后面的’\n’,那么代碼的運(yùn)行結(jié)果還與之前相同嗎?答案否定的,該代碼的運(yùn)行結(jié)果是:先休眠3秒,然后打印字符串hello world之后結(jié)束運(yùn)行。該現(xiàn)象就證明了行緩沖區(qū)的存在。
????????顯示器對(duì)應(yīng)的是行刷新,即當(dāng)緩沖區(qū)當(dāng)中遇到’\n’或是緩沖區(qū)被寫(xiě)滿才會(huì)被打印出來(lái),而在第二份代碼當(dāng)中并沒(méi)有’\n’,所以字符串hello world先被寫(xiě)到緩沖區(qū)當(dāng)中去了,然后休眠3秒后,直到程序運(yùn)行結(jié)束時(shí)才將hello world打印到顯示器當(dāng)中。
? \r和\n
????????\r:?回車(chē),使光標(biāo)回到本行行首。
????????\n:?換行,使光標(biāo)下移一格。
????????既然是\r是使光標(biāo)回到本行行首,那么如果我們向顯示器上寫(xiě)了一個(gè)數(shù)之后再讓光標(biāo)回到本行行首,然后再寫(xiě)一個(gè)數(shù),不就相當(dāng)于將前面一個(gè)數(shù)字覆蓋了嗎?
????????但這里有一個(gè)問(wèn)題:不使用’\n’進(jìn)行換行怎么將緩沖區(qū)當(dāng)中數(shù)據(jù)打印出來(lái)?
????????這里我們可以使用fflush函數(shù),該函數(shù)可以刷新緩沖區(qū),即將緩沖區(qū)當(dāng)中的數(shù)據(jù)刷新當(dāng)顯示器當(dāng)中。
????????對(duì)此我們可以編寫(xiě)一個(gè)倒計(jì)時(shí)的程序。
? 進(jìn)度條代碼
Makefile:
processbar.h:
processbar.c:
main.c:
代碼效果:
Gitee上傳代碼
????????首先我們需要在gitee上注冊(cè)一個(gè)倉(cāng)庫(kù),再將我們的倉(cāng)庫(kù)克隆到Linux系統(tǒng)中,如下圖所示
????????在Linux系統(tǒng)上安裝git工具?
russleo@VM-0-2-ubuntu:~$ sudo apt install -y git
? ? ? ? ?再將需要上傳的目錄復(fù)制到倉(cāng)庫(kù)目錄下
????????再依次進(jìn)行add,?commit -m ,push操作
????????如果沒(méi)有顯示錯(cuò)誤信息,我們就可以在gitee網(wǎng)站上看到我們所上傳的文件及目錄。?
Linux調(diào)試器 - gdb
? gdb使用須知
程序發(fā)布方式:
?1、debug版本:程序本身會(huì)被加入更多的調(diào)試信息,以便于進(jìn)行調(diào)試。
?2、release版本:不會(huì)添加任何調(diào)試信息,是不可調(diào)試的。
????????在Linux當(dāng)中g(shù)cc/g++默認(rèn)生成的可執(zhí)行程序是release版本的,是不可被調(diào)試的。如果想生成debug版本,就需要在使用gcc/g++生成可執(zhí)行程序時(shí)加上-g選項(xiàng)。?
????????對(duì)同一份源代碼分別生成其release版本和debug版本的可執(zhí)行程序,并通過(guò)ll指令可以看到,debug版本發(fā)布的可執(zhí)行程序的大小比release版本發(fā)布的可執(zhí)行程序的大小要大一點(diǎn),其原因就是以debug版本發(fā)布的可執(zhí)行程序當(dāng)中包含了更多的調(diào)試信息。?
gdb命令匯總
【進(jìn)入gdb】
指令: gdb?文件名
【調(diào)試】
1)「run/r」:運(yùn)行代碼(啟動(dòng)調(diào)試)。
2)「next/n」:逐過(guò)程調(diào)試。
3)「step/s」:逐語(yǔ)句調(diào)試。
4)「until?行號(hào)」:跳轉(zhuǎn)至指定行。
5)「finish」:執(zhí)行完當(dāng)前正在調(diào)用的函數(shù)后停下來(lái)(不能是主函數(shù))。
6)「continue/c」:運(yùn)行到下一個(gè)斷點(diǎn)處。
7)「set?var?變量=x」:修改變量的值為x。
【顯示】
1)「list/l?n」:顯示從第n行開(kāi)始的源代碼,每次顯示10行,若n未給出則默認(rèn)從上次的位置往下顯示.。
2)「list/l?函數(shù)名」:顯示該函數(shù)的源代碼。
3)「print/p?變量」:打印變量的值。
4)「print/p?&變量」:打印變量的地址。
5)「print/p?表達(dá)式」:打印表達(dá)式的值,通過(guò)表達(dá)式可以修改變量的值。
6)「display?變量」:將變量加入常顯示(每次停下來(lái)都顯示它的值)。
7)「display?&變量」:將變量的地址加入常顯示。
8)「undisplay?編號(hào)」:取消指定編號(hào)變量的常顯示。
9)「bt」:查看各級(jí)函數(shù)調(diào)用及參數(shù)。
10)「info/i?locals」:查看當(dāng)前棧幀當(dāng)中局部變量的值。
【斷點(diǎn)】
1)「break/b?n」:在第n行設(shè)置斷點(diǎn)。
2)「break/b?函數(shù)名」:在某函數(shù)體內(nèi)第一行設(shè)置斷點(diǎn)。
3)「info?breakpoint/b」:查看已打斷點(diǎn)信息。
4)「delete/d?編號(hào)」:刪除指定編號(hào)的斷點(diǎn)。
5)「disable?編號(hào)」:禁用指定編號(hào)的斷點(diǎn)。
6)「enable?編號(hào)」:啟用指定編號(hào)的斷點(diǎn)。
【退出gdb】
1)「quit/q」:退出gdb。