Linux學習筆記-基本操作4
1. gdb調試
2. makefile的編寫
3. 系統IO函數
1. gdb調試:
1. 啟動gdb + 可執行文件
2. 查看代碼:
l==list
l (默認給出main函數的前十行)(再次輸入l會給繼續列出後面的內容 之後可以按回車即可)
l 行號(或函數名)
l filename:行號(或函數名)
3. 設置斷點:
設置當前文件斷點:
b == break
b 行號(或函數名)
設置指定文件斷點:
b fileName:行號(函數名)
設置條件斷點:
b 10 if 某個變量==19
刪除斷點:
delete == del == d
d 斷點的編號
獲取編號:
info == i
info b
4. 查看設置的斷點
i==info
i b
5. 開始 執行gdb調試
執行一步操作: start (或r==run 直接運行或到斷點停止)
單步繼續執行: n
執行多步, 直接停在斷點處:c
5. 單步調試
進入函數體內部: s
從函數體內部跳出: finish
不進入函數體內部: n
退出當前循環: u
6. 查看變量的值: p == print
p 變量名
7. 查看變量的類型: ptype 變量名
8. 設置變量的值: set var 變量名 = 賦值
9. 設置追蹤變量
display + 變量名
取消追蹤變量 :undisplay 編號
獲取編號: info display
10. 退出gdb調試
quit
2. makefile的編寫:項目的代碼管理工具,節省編譯項目的時間,一次編寫終身受益
1. makefile的命名:makefile (或Makefile)
2. makefile的規則:(vi makefile 直接創建文件)
規則中的三要素: 目標(app名字), 依賴(用到的.c文件), 命令(gcc命令)
目標:依賴條件
(tab縮進)命令
子目標和終極目標的關系: 生成最終目標
用戶自定義的規則:
clean:
(-makedir \aa 不能成功,不加-則在此處命令暫停,加-則可以忽略該命令向下繼續執行)
rm *.o -f (-f強制刪除,即使沒有)
make clean (執行對應的clean規則的命令)
若當前目錄下有名為clean的文件,則不能執行相應規則
解決方案 -->在前一行做偽目標聲明:.PHONY:clean
3.執行makefile生成終極目標app:make (會在下一行顯示一些gcc命令) 4.若想生成目標,檢查規則中的依賴條件是否存在,如果不存在,尋找是否有規則用來生成該依賴文件。檢查規則中的目標是否需要更新,必須檢查它的所有依賴,依賴中有任意一個被更新,則目標必須更新。依賴文件比目標文件時間晚,則需要更新。
5.可以在makefile 中聲明變量如obj=main.o sum.o sub.o
使用變量:$(obj)
6. makefile的兩個函數(makefile中所有的函數必須都有返回值)
wildcard:查找指定目錄下指定類型的文件,一個參數
src = $(wildcard ./*.c) 找到./src 目錄下所有後綴為.c的文件,以串的形式賦給變量src
patsubst:匹配替換,從src中找到所有.c 結尾的文件,並將其替換為.o
obj = $(patsubst %.c ,%.o ,$(src)) 把src變量中所有後綴為.c的文件替換成.o
7. makefile中的自動變量
$<: 規則中的第一個依賴
$@: 規則中的目標
$^: 規則中的所有依賴
只能在規則的命令中使用
app:main.o sub.o mul.o
gcc main.o sub.o mul.o -o app
(gcc $^ -o $@)
%.o:%.c (第一個%逐個匹配終極目標的依賴,第二個%匹配第一個%內容)
gcc -c $< -o $@
8.Makefile自己維護的變量,都是大寫的。
CC = cc (gcc)
CPPFLAGS : 預處理器需要的選項 如:-I
CFLAGS:編譯的時候使用的參數 –Wall –g -c
LDFLAGS :鏈接庫使用的選項 –L -l
用戶可以修改這些變量的默認值CC = gcc
3. 系統IO函數
1>. 一些概念
文件描述符
PCB
庫函數與系統函數的關系
2>. open
函數原型:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
打開方式:
必選項flags:
O_RDONLY 只讀
O_WRONLY 只寫
O_RDWR 讀寫
可選項:
O_CREAT 創建新文件
第三個參數:文件權限: 本地有一個掩碼:umask 可查看 umask 022 可臨時修改
文件的實際權限: 給定的權限 & 本地掩碼(取反)==實際的文件權限
7 7 7
111111111(給定權限的8進制)
111111101(掩碼去反的8進制)
---------
111111101
7 7 5
O_EXCL 如果同時指定了O_CREAT,並且文件已存在,則出錯返回。<stdio.h>void perror(const char *s)用來將上一個函數發生錯誤的原因輸出到標準設備(stderr)
O_TRUNC 將文件截斷為0,如果文件已存在,則將其長度截斷(Truncate)為0字節。
O_APPEND 追加如果文件已有內容,這次打開文件所寫的數據附加到文件的末尾。
3>. read 從打開的設備或文件中讀取數據。
函數原型:ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符
buf:數據緩沖區
count:請求讀取的字節數
返回值:
1. -1 讀文件失敗
2. 0 文件讀完了
3. >0 讀取的字節數
4>. write 向打開的設備或文件中寫數據。
函數原型:ssize_t write(int fd, const void *buf, size_t count);
返回值:
-1 --> 失敗
>=0 --> 寫入文件的字節數
5>. lseek 修改文件偏移量(讀寫位置) 。文件的拓展, 最後需要做額外的寫操作 。
函數原型:off_t lseek(int fd, off_t offset, int whence)
off_t offset --> 偏移量
int whence --> 偏移位置
SEEK_SET - 從文件頭向後偏移
SEEK_CUR - 從當前位置向後偏移
SEEK_END - 從文件尾部向後偏移
返回值:
較文件起始位置向後的偏移量
允許超過文件結尾設置偏移量,文件會因此被拓展。
失敗返回 -1
獲取文件長度:lseek(fd, 0, SEEK_END); 返回值即為文件長度
6>. close
參數:open函數的返回值
返回值:
0 --> 正常關閉
-1 --> 關閉出現錯誤
cpu 為什麽要使用虛擬地址空間與物理地址空間映射?解決了什麽樣的問題?
1.方便編譯器和操作系統安排程序的地址分布。
程序可以使用一系列相鄰的虛擬地址來訪問物理內存中不相鄰的大內存緩沖區。
2.方便進程之間隔離
不同進程使用的虛擬地址彼此隔離。一個進程中的代碼無法更改正在由另一進程使用的物理內存。
3.方便OS使用你那可憐的內存。
程序可以使用一系列虛擬地址來訪問大於可用物理內存的內存緩沖區。當物理內存的供應量變小時,
內存管理器會將物理內存頁(通常大小為 4 KB)保存到磁盤文件。數據或代碼頁會根據需要在物理內存與磁盤之間移動。
對大文件的讀寫兩種方式:
read write -- 每次讀1個byte 效率低
getc putc -- 每次讀1個byte 效率高
標準C庫函數內部提供了一個緩沖區
Linux學習筆記-基本操作4