大綱:命令,vim,gcc,編譯工具,生成代碼,調試,庫makefile,系統編程
文件系統:文件屬性,文件內容,萬物皆文件(不在內存中的是文件,鼠標鍵盤耳機都可以看作鍵盤),IO多路復用(即時聊天),進程(特點(怎么分配資源),多進程(創建和管理),),進程間通信(管道,共享內存,信號量,消息隊列,信號),線程(多線程,互斥和同步,),網絡(網絡概念,編程,epoll,),服務器結構(進程池和線程池),sql語句,最終實現一個網盤。
1、gcc
? ? ? ? 預處理處理#開頭的文件,
寫代碼一般就編譯錯誤(語法錯誤)或者鏈接錯誤(名字沖突)
2、匯編(AT&T語言(匯編的語言有很多種,AT&T語言是其中一種,針對x86機器))
編譯后所有的名字都轉換成內存的地址;所有的類型的信息都變成長度信息;
????????
pushq? ? (push表示壓棧,q表示quadra(4),表示四倍16bit就是64bit,x86的8086是16bit一個字長(每次讀取內存的單位),)
%rbp(百分號說明是一個寄存器,register? base? pointer,表示基地址)?
movq? 表示拷貝
subq? ? sub表示減, rsp減去48;
q表示四個字長,一個字長16位為兩個字節,
xorl? (xor表示異或,L表示兩個字長32位);$表示賦值;
每四個字節為單位:
變量的名字和類型會被轉化為內存的位置和內存的大小;
leaq(lea表示load effective address? ,取地址)
call? (調用函數);
存儲程序的概念:
在需要調用mian意外的函數時先call這個函數,然后把用一個占位符占位,等鏈接的時候,再進入函數;
新壓一個棧來
參數傳遞:caller的棧幀到寄存器到caller的棧幀,值傳遞的過程;
字符串字面常量:存于rdi區,(只讀)
esi和rdi是為了調用printf
?fun? return 后回到main;
jmp 指針移動;(for? 循環)循環的底層用goto實現
cmpl(比較);
jle(jump less equal):小于等于就跳轉;編譯器會優化部分代碼(等價替換)
je? 相等就跳轉;
call? ——stack——chk——fail@PLT? (提示棧損毀);如果內存發生修改就證明代碼錯誤;所以引出報錯;指針內存亂指等原因;
--------------------匯編總結------------
push (壓棧) pop(出棧) call(調用函數) ret(函數返回)
mov (拷貝)? add(加)? sub(減)lea(取地址)
xor(異或) jmp je jle? ? (跳轉)
q(8byte) l(4byte)
所有變量,數組,*p 編譯完在匯編中只剩下了地址+長度
循環 for,while,和goto本質一樣
函數調用 棧幀獨立,傳遞參數值傳遞
AS命令,生成匯編文件
可移植GUN匯編
nm命令(列出文件中的符號信息)
常見符號類型:A(該符號的值在今后的鏈接中不再改變)
U(該符號未定義過,需要自其他對象文件中鏈接出來)
T(該符號在代碼段中,通常是全局非靜態函數)
gcc -c? (.c 文件直接生成.o)
objdump (反編譯)
反編譯匯編文件可以把.o(機器語言)反編譯成.s(匯編語言)
以上左側二進制序列對應右側匯編代碼
鏈接(參考書《linker &loader》《程序員自我修養》)
把調用函數的名字換成地址;
ld 命令(鏈接文件)
或者使用gcc命令間接調用鏈接;
(函數 / 全局變量 定義0次/超過2次)? (缺失main函數) (報錯信息有ld錯誤)鏈接錯誤;
執行可執行程序
./ 文件名? ?(防止與文件名沖突)
庫文件(特殊的.o文件)
靜態庫和動態庫
靜態庫(打包到產品中)
動態庫(運行時才加載到產品中)
ldd 查看文件依賴庫
-static 選項讓文件鏈接依賴靜態庫;默認動態庫
靜態編譯占用內存較大
生成靜態庫:
ar命令:創建、修改庫、從庫中提出單個模塊;
?
1、通過gcc -c add.c -o add.o 生成目標文件
2、打包成靜態庫文件
ar crsv libadd.a add.o
3、移動到系統搜索目錄? /usr/lib
sudo cp libadd.a /usr/lib
4、在鏈接文件時加上? -ladd
靜態庫鏈接成功后生成的可執行文件不會因為原靜態庫的丟失而受影響;
生成動態庫:
1、編譯成目標文件
?動態庫加載于棧區和堆區之間,該區域命名為共享庫映射區,該區不能生成絕對地址。
這樣生成的代碼叫位置無關代碼
-fpic (編譯時加上這個選項即可完成)
gcc add.c -o add.o -fpic? ?(編譯)
2、打包
gcc -shared add.o -o libadd.so
3、移動到系統庫目錄
sudo cp libadd.so /usr/lib
4、鏈接加上-ladd
gcc test.o -o test -ladd
ldd 文件名(查看動態庫的鏈接情況)
刪除libadd.so后可執行文件失效;重新copy后可以運行,修改鏈接庫文件后不用鏈接即可在線更新;
更新出bug后進行回滾:
軟連接(符號鏈接)類似于windows的快捷方式
用版本號來區別更新前后的文件,軟連接來鏈接需要的文件
將動態庫文件libadd.so文件移動到libadd.so.0.1后執行test顯示找不到庫文件;
ln -s命令可以創建軟鏈接
創建軟連接成功后用ls -al 可以查看
鏈接創建后可以執行文件
gcc的其他選項:
-D 選項
預處理時需要用到ifdef 為了避免重復改代碼造成的風險,可以注釋掉需要定義的宏,在預處理階段加入-D命令使預處理生效注釋掉的宏。
-I?選項(大寫i)
增加一個搜索路徑,防止重復修改文件目錄,導致在源代碼里面多次修改導致不可預測的風險。利用改變命令的方式來改變搜索路徑。
-O(編譯優化,結果不變,指令數量變少,執行速度變快(編譯器作者在不影響結果的情況下修改指令順序和數據存儲位置))
可能會對調試影響(單步調試)編譯優化分級來減小對代碼調試的影響
-O0? ? ? 不優化
-O1? ? ? ? 發布產品
-O2? ? ? ? 開源軟件
-O3? ? ? ?激進優化方案
????????????????優化越深
優化越深,c于匯編的對應就亂了。
編譯警告:
Linux中不能出現警告。
警告實例:在源代碼中定義了 i 但是沒有用到;
gdb--調試工具
?不能開優化,該工具針對c代碼的一行,? -O0
補充調試信息,? -g
以上兩點要在編譯時加上。
使用-O0和-g后生成可執行程序中包含了調試信息;
gbd 文件名(可執行文件名)進入gdb調式界面
list (每十行顯示源代碼)list后面加行號可從行號顯示;l 和list一樣的效果
list 加文件名 加行號 函數名
run? / r運行程序
break /b(打斷點)加文件名加行號 加函數(在函數定義入口打斷點)
continue / c? 運行到下一個斷點
step / s 單步調試? vs的f11,進入函數第一行(逐步進入)
next / n? ? vs的f10 單步調用但是跳過函數(逐步越過)
finish? ? 直接運行這個函數調用完為止;跳出本次函數調用
info break? /i b查看目前的所有斷點
delete 加編號? ?刪除斷點(不加編號就刪除全部)
進入循環斷點時,gdb會進入這個斷點循環次數,所以需要用到忽略這個斷點若干次
多次命中循環體中的斷點
ignore忽略斷點若干次(測試循環結構)
使用i b 查看斷點編號,再用ignore 加斷點編號加次數設置忽略次數
已經忽略三次循環的效果
在gdb中查看監視
print? / p
p為指針(內存空間以指針大小偏移,int為4byte,所以地址偏移四字節進四。內存的一個字節對應一個地址)
自動監視變量的值,display 加變量名
每查看一行就自動監視輸出一次
刪除display
先info display顯示display的編號再undisplay 加編號刪除
help 加命令 顯示手冊
X 在gdb中去查看內存:

FMT = 數字? 字母1 字母2
數字:查看多少單位
字母1:O(八進制)x(十六進制)d(十進制) u(無符號十進制)t(二進制)
字母2:每個單位的大小 b(1byte)h(halfword,2byte)w(word,4byte) g (giant , 8 bytes)
??例子:arr數組3個字節
x/3tw arr
3個單位 二進制的形式4個字節
4個單位,二進制,4字節
檢查崩潰的程序
core文件-----記錄程序崩潰的時刻內存的堆棧情況。
指針在解引用和初始化之前不能賦值,不然會造成野指針。
錯誤實例:
段錯誤:Segmentation fault
core dumped (core文件儲存)操作系統會限制core文件的大小
ulimit -a (查看操作系統限制大小)
ulimit -c unlimited? ?(設置core文件 不限制大小)
該指令不是永久生效,只能影響一個終端;
修改以下文件,來修改core的大小限制
切換到root用戶
用echo? core >?/proc/sys/kernel/core_pattern
往core_pattern 寫入core
之后core文件獲得不限制大小的權限,即可生成core文件
gdb 可執行文件名?core(該命令用于查看core文件內容)
獲得報錯信息,
bt命令用于調用堆棧的情況
1、編譯時加上 -g -O0
2、ulimit -c unlimited
3、執行程序
4、gdb? 可執行程序? core
棧溢出導致的崩潰
?
命令行參數 + gdb:
用gdb啟動:
set args how are you(設置追加參數,)
show args (展示追加的參數)