Linux編程環境
【學習筆記】
vi編輯器
vi 檔案名 #進入檔案編輯模式
一般模式:
yy #復制當前行
y數字y #復制多少行內容
p #箭頭移動到目的行粘貼
u #撤銷上一步
dd #洗掉當前行
d數字d #洗掉游標后多少行
x #洗掉一個字母(相當于delete)
X #洗掉一個字母(相當于backspace)
yw #復制一個詞
dw #洗掉一個詞
shift+^ #移動到行頭
shift+4 #移動到行尾
1+shift+g #移動到頁頭
shift+g #移動到頁尾
N+shift+g #移動到目標行
編輯模式:
i #當前游標前
a #當前游標后
o #當前游標行的下一行
delete #洗掉
esc #退出編輯模式
指令模式:
:w #保存
:q #退出
! #強制執行
:wq! #強制保存退出
gcc編譯器
GCC 是一個交叉平臺編譯器,能夠在當前CPU 平臺上為多種不同體系結構的硬體平臺開發軟體,因此尤其適合在嵌入式領域的開發編譯,
gcc編譯支持檔案
.c,C 語言源代碼
.h,程式所包含的頭檔案
.i,已經預處理過的C 源代碼檔案
.s,匯編語言源代碼檔案
.o,編譯后的目標檔案
gcc編譯流程
寫個hello.c源代碼
gcc hello.c
#include<stdio.h>
int main()
{
printf(“Hello world!\n”);
return 0;
}
保存、退出
1、預處理
該階段,編譯器將上述代碼中的stdio.h編譯起來,可用“-E”選項查看
gcc格式為
gcc [選項] 要編譯的檔案 [選項] [目標檔案] #目標檔案可預設,默認生成.out檔案
gcc -E hello.c -o hello.i #-o:指目標檔案;-i:指 已經預處理過的源程式
預編譯階段將“stdio.h”中的內容插入到hello.i檔案中
2、編譯
該階段,gcc首先檢查代碼的規范性、語法錯誤;檢查無誤后,gcc把代碼翻譯成匯編語言,可用“-S”選項查看
gcc -S hello.i -o hello.s
3、匯編
匯編階段是把編譯階段生成的“.s”檔案轉成目標檔案,讀者在此可使用選項“-C”看到匯編代碼已轉化為“.o”的二進制目標代碼,
gcc –c file.s –o file.o
4、鏈接
在預編譯中包含進的“stdio.h”中也只有該函式的宣告,而沒有定義函式的實作,那么,是在哪里實作“printf”函式的呢?答案是:系統把這些函式實作都做到名為libc.so.6 的庫檔案中去了,
在沒有特別指定時,gcc 會到系統默認的搜索路徑“/usr/lib”下進行查找,從而鏈接到libc.so.6 庫函式,這樣就能實作函式printf 了,這也就是鏈接的作用,
gcc file.o –o file
gcc編譯選項
gcc [選項] [檔案]
-E:使用此選項表示僅作預處理,不進行編譯、匯編和鏈接,
-S:編譯到匯編語言不進行匯編和鏈接,
-c:編譯到目標代碼,
-o:檔案輸出到檔案,
-static:此選項將禁止使用動態庫,所以,編譯出來的東西一般都很大,也不需要什么動態
鏈接庫即可運行,
-share:此選項將盡量使用動態庫,所以生成檔案比較小,但是需要系統有動態庫,
-I dir:在頭檔案的搜索路徑串列中添加dir 目錄,
-L dir:在庫檔案的搜索路徑串列中添加dir 目錄,
-llibrary:鏈接名為library 的庫檔案,
gdb除錯器
Linux 的大部分特色源自于Shell 的GNU(GNU symbolic debugger)除錯器,也稱作gdb
gdb使用流程
啟動gdb
以一段代碼為例
gcc gdb_sample.c
#冒泡排序
void bubble_sort(int arr[], int len) {
int temp;
for (int i = 0; i < len; i++) {
for (int j = 0; j < len-1-i; j++) {//從第一個數開始,依次和后一個數比較
if (arr[j] > arr[j + 1]) { #把較大的數交換到后邊
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
} #內層回圈結束后,最大一個數排到最后,保持不動
#每結束一次內層回圈,比較次數少一次,因此有-i
}
}
}
int main(){
int arr[] = { 22, 45, 67, 36, 93, 444, 26, 84, 3, 7 };
int len = (int)sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, len);
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
}
退出保存后使用gcc對代碼進行編譯,注意一定要加上選項“-g”,這樣編譯出的可
執行代碼中才包含除錯資訊,否則之后gdb 無法載入該可執行檔案,
啟動gdb進行除錯:
gcc -g gdb_sample.c -o gdb_sample
在gdb輸入命令時,可用不用打全命令,在Linux下,可用敲擊兩次Tab鍵來補全命令,
除錯命令
查看檔案
輸入l(list),查看所載入的檔案(輸入l即可,系統會自動識別)
設定斷點
break <function> #在進入指定函式時停住
break <linenum> #在指定行號停住
break +offset,break -offset #在當前行號的前面或后面的offset 行停住
break filename:linenum #在源檔案filename 的linenum 行處停住
break filename:function #在源檔案filename 的function 函式的入口處停住
break *address #在程式運行的記憶體地址處停住
break #break 命令沒有引數時,表示在下一條指令處停住
break…if <condition> #…可以是上述的引數,condition 表示條件,在條件成立時停住
查看斷點
info breakpoints [n]
info break [n]
運行代碼
輸入r(run)即可,gdb 默認從首行開始運行代碼,若想從
程式中指定行開始運行,可在r 后面加上行號:
r 10 #第十行開始執行
查看變數值
p [變數]
恢復程式運行和單步運行
step <count> #單步跟蹤,如果有函式呼叫,它會進入該函式
next <count> #同樣單步跟蹤,但如果有函式呼叫,不會進入該函式
set step-mode,set step-mode on #打開step-mode 模式
set step-mod off #關閉step-mode 模式
finish #運行程式,直到當前函式完成回傳
until 或u #當你厭倦了在一個回圈體內單步跟蹤時,這個命令可以運行程式直到退出回圈體
Make工程管理
Makefile基本規則
一個簡單的Makefile:結構組成
all: #目標名字放在":"前面,名字由字母和下劃線組成
#":"后面是需要鏈接的檔案
echo "Hello World" #注意echo前必須有一個Tab鍵位,不能是空格
#echo 后面是生成目標的命令
test:
echo "Test Target" #一個makefile可以定義多個目標
實體演示
vi max.h
int max (int a, int b);
vi max.c
int max(int a,int b){
if(a>=b){
return a;
}
else{
return b;
}
}
vi min.h
int min(int a,int b);
vi min.c
int min(int a,int b){
if(a<b){
return a;
}
else{
return b;
}
}
vi main.c
#include <stdio.h>
#include "max.h"
#include "min.h"
int main(int argc, char* argv[]){
int a = 5;
int b = 3;
int maxNum= max(a,b);
int minNum = min(a,b);
printf("the max value is %d\nthe min value is %d\n",maxNum,minNum);
return 0;
}
一般編譯流程
首先編譯依賴庫檔案,然后編譯main函式
編譯依賴庫
編譯max.c
gcc -c max.c -o max.o
編譯min.c
gcc -c min.c -o min.o
編譯main函式
編譯main.c
gcc max.o min.o main.c -o main
執行main
./main
輸出結果
the max value is 5
the min value is 3
如果依賴函式過多,或者呼叫o庫檔案多,這樣編譯將非常麻煩
于是采用makefile方式來進行簡化
Makefile編譯方式
創建Makefile檔案
vi Makefile #創建Makefile
#編輯Makefile(模板)
simple:main.o max.o min.o
gcc -o simple main.o max.o min.o #Tab間隔
main.o:main.c
gcc -c main.c -o main.o
max.o:max.c
gcc -c max.c -o max.o
min.o:min.c
gcc -c min.c -o min.c
運行Makefile
方法一:在Makefile所在的目錄下運行命令
make
方法二:運行命令make all
make [目標名]
輸出
gcc -c max.c -o max.o
gcc -c min.c -o min.o
gcc max.o min.o main.c -o simple
執行
./simple
輸出
the max value is 5
the min value is 3
Makefile假目標
在前面的simple 專案中,現在假設在程式所在的目錄下面有一個clean 檔案,這個檔案也可以用過touch命令來創建,
假目標可以采用.PHONY關鍵字來定義,需要注意的是其必須是大寫字母
.PHONY:clean #假目標
simple:main.o max.o min.o
gcc -o simple main.o max.o min.o #Tab間隔
main.o:main.c
gcc -c main.c -o main.o
max.o:max.c
gcc -c max.c -o max.o
min.o:min.c
gcc -c min.c -o min.c
clean:
rm main.o min.o max.o simple
采用.PHONY 關鍵字宣告一個目標后,make 并不會將其當作一個檔案來處理,而只是當作一個概念上的目標,對于假目標,我們可以想像的是由于并不與檔案關聯,所以每一次make 這個假目標時,其所在的規則中的命令都會被執行
Makefile變數
在Makefile 中通過使用變數來使得它更簡潔、更具可維護性
自動變數
$@ #表示一個規則中的目標,當我們的一個規則中有多個目標時,$@所指的是其中任何造成命令被運行的目標,(表示的是目標的集合)
$^ #表示的是規則中的所有先擇條件,(表示的是依賴的集合)
$< #表示的是規則中的第一個先決條件,(表示目標串列里最后一個依賴)
【注意】由于在Makefile 中“$”具有特殊含義,因此,如果想采用echo 輸出“$”,則必需用兩個連著的“$”,還有就是,“$@”對于Shell 也有特殊的意思,我們需要
在“$$@”之前再加一個脫字符“\”,
其他一些字符的表示:
%.o 表示所有的.o檔案
%.c 表示所有的.c檔案
實體:
.PHONY:clean
CC = gcc #定義變數
RM = rm
OBJ = simple
OBJS = main.o max.o min.o
$(OBJ):$(OBJS)
$(CC) -o $@ $^
main.o:main.c
$(CC) -c $^ -o $@
max.o:max.c
$(CC) -c $^ -o $@
min.o:min.c
$(CC) -c $^ -o $@
clean:
@$(RM) $(OBJS) $(OBJ)
Makefile函式
addprefix函式
addprefix 函式是用來給字串中的每個子串前加上一個前綴,其形式是:$(addprefix prefix, names…)
.PHONY:all
SOURCE = main.c max.c min.c
OBJS = /home/pyma/Makefile
add source = $(addprefix $(OBJS)/. $(SOURCE))
all:
@echo $(add_source)
filter函式
filter 函式用于從一個字串中,根據模式得到滿足模式的字串,其形式是:$(filter pattern..., text)
.PHONY:all
SOURCE = main.c max.c min.c
OBJS = /home/pyma/Makefile
add source = $(addprefix $(OBJS)/. $(SOURCE))
sources = $(filter %.c %.s,$(add_source)
all:
@echo $(add_source)
從結果來看,經過filter 函式的呼叫以后,sources 變數中只存在.c 檔案和.s 檔案,而.h 檔案則被過濾掉了
filter-out函式
filter-out 函式用于從一個字串中根據模式濾除一部分字串,其形式是:$(filter-out pattern..., text)
.PHONY:all
SOURCE = main.c max.c min.c
OBJS = /home/pyma/Makefile
add source = $(addprefix $(OBJS)/. $(SOURCE))
sources = $(filter-out %.h,$(add_source)
all:
@echo $(add_source)
從結果來看,filter-out 函式將以“.h”為后綴的檔案從add_source 變數中給濾除了,可以看出,filter 與filter-out 是互補的
wildcard函式
wildcard 是通配符函式,通過它可以得到我們所需的檔案,這個函式相當于我們在Windows或是Linux 命令列中的“*”,其形式是:$(wildcard pattern)
.PHONY:all
SOURCE = $(wildcard *.c)
OBJS = /home/pyma/Makefile
add source = $(addprefix $(OBJS)/. $(SOURCE))
all:
@echo $(add_source)
運行結果:從當前Makefile 所在的目錄下通過wildcard 函式得到所有的C 程式源檔案
patsubst函式
patsubst 函式是用來進行字串替換的,其形式是:$(patsubst pattern, replacement, text)
.PHONY:clean
CC = gcc #定義變數
RM = rm
OBJ = simple
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
$(OBJ):$(OBJS)
$(CC) -O $@ $^
main.o:main.c
$(CC) -c $^ -o $@
max.o:max.c
$(CC) -c $^ -o $@
min.o:min.c
$(CC) -c $^ -o $@
clean:
@$(RM) $(OBJS) $(OBJ)
OBJS 變數中采用patsubst 函式進行字串替換,將所有的.c 檔案都替換成.o 檔案,patsubst 函式可以使用模式,所以其也可以用于替換前綴等,功能更加強大
選自華清遠見《嵌入式作業系統》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/285830.html
標籤:其他
上一篇:通訊總線總結
下一篇:Shell編程
