2018-2019-1 20189215《Linux核心原理與分析》第二週作業
阿新 • • 發佈:2018-11-07
本週學習了《庖丁解牛》第1章,以及《Linux核心設計與實現》第1、2、18章。通過視訊和實驗,學會了反彙編一個簡單的C程式,也學習了Linux核心除錯的一些小技巧和printk
函式。
反彙編一個簡單的C程式
- 程式編寫及編譯
- 使用
vi
編輯原始碼
返回值是15,我學號的後兩位。 - 使用
gcc
命令編譯為32位的彙編程式碼
- 彙編程式碼
- 使用
:g
刪除輔助資訊
- 精簡後的彙編程式碼
- 彙編程式碼分析
接下來逐行分析堆疊、暫存器的變化。在此採用了和書中一樣的簡化表示方法,減4位轉化為加1位,對應下移一格;加4位轉化為減1位;對應為上移1格。
- 初始狀態
- 第18行
將ebp
的值壓棧,esp
減1,下移一格。 - 第19行
將esp
的值賦值給ebp
。 - 第20行
esp
下移一格。 - 第21行
立即定址,立即值7賦值到esp
所指的位置。 - 第22行
call f
相當於push %eip
(僅僅這樣表示 )和mov1 f, %eip
(僅僅這樣表示),因此下一行第23行入棧,esp
下移一格,並將f函式的第一行9賦值給eip
。 - 第9、10行
cpu從eip
讀取指令,程式執行第9行,將ebp
的值壓棧,esp
減1,下移一格。
第10行將esp
的值賦值給ebp
。
第9、10行相當enter
指令,用於建立函式堆疊。 - 第11行
esp
下移一格。 - 第12行
移位定址,將ebp
上移兩格後所指的值賦值給eax
。 - 第13行
將eax
的值賦值給esp
所指向的位置。 - 第14行
call g
相當於push %eip
(僅僅這樣表示 )和mov1 g, %eip
(僅僅這樣表示),因此下一行第15行入棧,esp
下移一格,並將g函式的第一行2賦值給eip
。 - 第2、3行
cpu從eip
讀取指令,程式執行第2行,將ebp
的值壓棧,esp
減1,下移一格。
第3行將esp
的值賦值給ebp
。
第2、3行相當enter
指令,用於建立函式堆疊。一共建立了2個站,後面需要2兩個leave
指令。 - 第4行
移位定址,將ebp
上移兩格後所指的值賦值給eax
- 第5行
將eax
的值加5,賦值給eax
。 - 第6行
出棧,並把值賦值給ebp
,賦值為4,ebp
指向4,esp
由於popl
操作上移一格。 - 第7行
ret
相當於popl %eip
(僅僅這樣表示),執行一次出棧操作,eip
值變成15,esp
上移一格。 - 第15行
cpu從eip
讀取指令,程式執行第15行,leave
是撤銷函式堆疊,相當於movl %ebp,%esp
和popl %ebp
,esp
先指向與ebp
相同的位置4,再進行一次出棧操作,ebp
的值變為1,指向位置1;esp
上移一格。 - 第16行
ret
執行一次出棧操作,eip
值變成23,esp
上移一格。 - 第23行
cpu從eip
讀取指令,程式執行第23行,將將eax
的值加3,賦值給eax
。 - 第24行
leave
是撤銷函式堆疊,相當於movl %ebp,%esp
和popl %ebp
,esp
先指向與ebp
相同的位置1,再進行一次出棧操作,ebp
的值變為0,指向位置0;esp
上移一格,也指向0。 - 第25行
ret
執行一次出棧操作,此時棧內已經無資料了。最後eax
是預設的儲存返回值的暫存器。
隨著程式的進行,堆疊也發生了變化,最後迴歸初始狀態。
《Linux核心設計與實現》讀書小結
閱讀本書,學會了一些與核心相關的知識。
- 使用
asm()
指令可以嵌入彙編程式碼。 - 分支宣告
likely
和unlikely
。 - 核心中記憶體不分頁,每多用一個位元組,實體記憶體就減少一個位元組。
- 核心並不能完美地支援浮點數的操作。
- 核心中要格外注意競爭條件引發的同步和併發。
- 除錯bug需要先找到bug,最好能夠復現。
- 在核心中使用
printk
函式。可以設定日誌級別,<0><1><2><3><4><5><6><7>分別對應不同緊急程度的資訊。 oops
是核心發出錯誤資訊、暫存器資訊、回溯資訊的方式。- 原子操作——能夠不分隔執行的程式碼;以及在執行中不能中斷否則就是完不成的程式碼。
- 核心呼叫
BUG_ON()
標記bug,提供斷言並輸出資訊,呼叫時會引發oops
。 - Magic SysRq key是除錯、挽救即將崩潰的系統所必須的工具。
- 探測系統可以使用UID(使用者ID)作為選擇條件(與程序有關),使用條件變數(與程序無關)或者統計量。還可以進行重複頻率限制和次數限制。
- 使用數學上的二分法可以更快的找出第一次BUG出現的核心版本。
總結
- 計算機是怎樣工作的?
採用用馮諾依曼體系結構的計算機,其核心是儲存程式計算機。這類計算機由記憶體、CPU、輸入裝置、輸出裝置組成。記憶體包括程式記憶體和資料記憶體,CPU包括運算器、控制器和暫存器。計算機在執行程式之前必須把要執行的相關程式和資料放入記憶體中,在執行程式時CPU根據當前程式指標暫存器的內容取出指令並執行指令,然後再取出下一條指令並執行,如此迴圈下去直到程式結束指令時才停止執行。其工作過程就是不斷地取指令和執行指令的過程,最後將計算的結果放入指令指定的儲存器地址中。