1. 程式人生 > >《Linux核心原理與分析》第五週作業

《Linux核心原理與分析》第五週作業

課本:第4章 系統呼叫的三層機制(上)

-使用者態、核心態和中斷
-使用者態:在低的執行級別下,程式碼能夠掌控的範圍有所限制,只能訪問部分記憶體。
-核心態:在高的執行級別下,程式碼可以執行特權指令,訪問任意的實體記憶體。
-中斷:從使用者態進入核心態的主要方式。
-中斷類別
- 硬體中斷:在使用者態程序執行時,硬體中斷訊號到來,進入核心態,就會執行這個中斷對應的中斷服務例程。
- 軟中斷:在使用者態程序執行過程中,呼叫了一個系統呼叫(一種特殊中斷),進入核心態。

  • 暫存器上下文切換
    當用戶態切換到核心態時,就要把使用者態暫存器上下文儲存起來,同時把核心態的暫存器的值放到當前CPU中。int指令觸發中斷機制會在堆疊上儲存一些暫存器的值,會儲存使用者態棧頂地址、當時的狀態字、當時的CS:EIP的值。同時會將核心態的棧頂地址、核心態的狀態字放入CPU對應的暫存器,並且CS:EIP暫存器的值會指向中斷處理程式的入口,對於系統呼叫來說是指向system_call。int指令或中斷訊號發生之後,第一件事就是儲存現場,進入中斷處理程式,執行SAVE_ALL。中斷處理程式結束後,中斷處理結束前的最後一件事是恢復現場,執行RESTORE_ALL。
  • API和系統呼叫關係
    • API:應用程式程式設計介面,只是函式定義。
    • 系統呼叫:是通過軟中斷向核心發出了中斷請求,int指令的執行就會觸發一箇中斷請求。
      libc函式庫定義的一些API內部使用了系統呼叫的封裝例程,其主要目的是釋出系統呼叫,使程式設計師在寫程式碼時不需要用匯編指令和暫存器傳遞引數來觸發系統呼叫。一個API可能只對應一個系統呼叫,亦可能內部由多個系統呼叫實現,一個系統呼叫也可能被多個API呼叫。
  • Intel x86 CPU定義了4種不同的執行級別0、1、2、3,數字越小特權越高。Linux系統採用了其中的0、3兩個特權級別。

實驗:使用庫函式API和C程式碼中嵌入彙編程式碼兩種方式使用同一個系統呼叫

在實驗樓環境中,我使用rename()系統呼叫來實現了將同目錄下的檔案更改檔名,C語言程式碼如下:

在Code資料夾中,我已經建立好一個名為“gzc.c”的檔案,如圖所示:

gcc執行上述C語言程式碼,成功改名,如圖所示:

經查詢,rename()的系統呼叫號為38:

38的16進位制數為0x26。所以,編寫彙編程式碼將其嵌入C語言程式碼,程式碼如下:

#include<stdio.h>

int main()
{
    char *old_name = "gzc123.c";
    char *new_name = "gzc.c";
    int ret;
    asm volatile(
            "movl %1,%%ebx\n\t"
            "movl %2,%%ecx\n\t"
            "movl $0x26,%%eax\n\t" //syscall num of rename in HEX is 0x26
            "int $0x80\n\t"
            :"=a"(ret)
            :"b"(old_name),"c"(new_name)
            );
    if(ret<0)
        printf("error!\n");
    else
        printf("successful!\n");
    return 0;
}

因為剛才在執行純C語言程式時已經將檔名改為"gzc123.c",這裡的彙編程式碼嵌入C程式碼是將“gzc123.c”改為“gzc.c”,程式同樣成功執行:

下面對嵌入的彙編程式碼進行分析:

"movl %1,%%ebx\n\t" //將old_name的值放入ebx
"movl %2,%%ecx\n\t" //將new_name的值放入ecx
"movl $0x26,%%eax\n\t" //syscall num of rename in HEX is 0x26
"int $0x80\n\t" //觸發系統呼叫
:"=a"(ret) //將eax的值寫入ret
:"b"(old_name),"c"(new_name) //分別代表上面的%1,%2

總結

本次實驗總體來說沒有遇到什麼編碼理解上的問題,僅僅遇到了一個小問題,就是在實驗樓環境執行程式碼編譯完成後的可執行程式時提示“許可權不足”,解決方法為在執行程式時在前面加上sudo,程式正常執行,如下所示:

本次實驗僅使用匯編程式碼實現了簡單的系統呼叫功能,實驗比較容易,但使我對於彙編程式碼的編寫和其執行過程更加熟悉和了解。希望在後面的實驗中,理解和編寫彙編程式碼、理解linux核心系統的執行會更加得心應手。