1. 程式人生 > >《Linux內核原理與設計》第五周作業

《Linux內核原理與設計》第五周作業

設計 起點 圖片 數學 包括 實現 \n 進程id cloud

使用庫函數API和C代碼中嵌入匯編代碼兩種方式使用同一個系統調用

方法一:使用庫函數API在屏幕上顯示進程的ID

    先在實驗樓中打開XFCE,在目錄下輸入指令: vi getpid.c;新建並打開getpid.c文件。

    隨後再在VI中輸入在網上查閱的實現getpid的函數代碼後,保存並退出。

    隨後再同gcc將該函數代碼進行編譯。再通過輸入指令./getpid即可得出目前進程的ID為:22056.

技術分享圖片

技術分享圖片

這種方式是用C語言使用庫函數API進行系統調用。

方法二:使用C語言內嵌匯編代碼在屏幕上顯示進程ID

技術分享圖片

技術分享圖片

對於內嵌匯編調用system_call()

    1、系統調用號放入eax中。

    2、系統調用的參數,按照順序存入相應寄存器中。

    3、返回值使用eax傳遞值。

     因為中斷(包括異常)是從用戶態進入內核態的唯一方式,所以在上述代碼中使用了中斷(“int $s0x80\n\t”這句),然後中斷處理程序SAVE_ALL保存現場,隨後就進入了內核態

進行下一步的操作。
  • 中斷處理
     中斷處理是從用戶態進入內核態主要的方式,系統調用是一種特殊的中斷。

     中斷處理的完整過程(由中斷信號或者int指令完成): 將cs:eip的值,堆棧段寄存器當前的棧頂(ss:eip)和當前的標誌寄存器(eflags)保存到內核堆棧中;同時將當前中斷服

務例程的入口加載到cs:eip中,當前堆棧段和eip也加載到CPU中。執行完以上以上步驟之後,當前CPU在執行下一條指令時,就已經開始執行整個中斷處理程序的入口了。此時已經

開始操作內核態的堆棧了。

     若完成中斷服務之後不發生進程調度,則繼續執行指令(RESTORE_ALL和iret),然後返回到原來的狀態;

     若發生進程調度,那麽當前發生的狀態都會暫時的保存在系統中,當下一次發生調度再次回到當前進程時就繼續執行指令RESTORE_ALL和iret。
  • 系統調用的工作機制:

技術分享圖片

      用戶態中xyz()函數就是系統調用對應的API;

      這個API中封裝了一個系統調用,這個系統調用會觸發int 0x80的一個中斷;

      0x80這個中斷向量就對應著system_call(內核代碼的入口起點);

      內核代碼中可能會執行到對應的中斷服務程序sys_xyz();

      在中斷服務程序執行完之後,可能會執行ret指令,此時可能會發生進程調度;

      如果沒有發生進程調度,就執行iret,返回到用戶態接著執行其他指令。

###實驗總結:

       即便是最簡單的程序,也難免要用到諸如輸入、輸出以及推出等操作,而要進行這些操作則需要調用操作系統所提供的服務,也就是系統調用。除非程序中只完成加減乘除等數學

算法,否則將很難避免使用系統調用。在Linux平臺下有兩種方式來采用系統調用:利用封裝後的C庫或者通過匯編直接調用。

      這次實驗,我知道了如何進行系統調用,但是對於代碼,我只能選擇借鑒,匯編的知識也不太熟練,不過這次實驗讓我更加熟悉了系統調用的本質和系統調用與中斷的關聯。中斷

處理是從用戶態進入內核態的主要方式,系統調用是一種特殊的中斷。

###系統調用的工作機制:

       1、用戶態中的xyz()函數就是系統調用所對應的系統API;

       2、在這個API中將系統調用封裝好,並在執行時觸發int 0x80這個中斷。對應內核態的system_call();
 
       3、system_call()中可能會執行中斷服務程序sys_xyz()

《Linux內核原理與設計》第五周作業