linux中的系統調用機制

張建幫 原創作品轉載請註明出處 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000

關於linux的系統調用,以下這張圖片可以解釋得比較清楚:

這裏寫圖片描述

這幅圖片以fork()函數爲例,詳細闡述了系統調用的具體的步驟與流程:

  1. 在源文件中使用的 fork() 函數會調用函數庫中的 fork()函數
  2. 函數庫中的fork()會將 sys_fork 的系統調用號 2 保存在 eax 寄存器中,然後調用 int $0x80 指令自陷,進入內核態
  3. 系統根據立即數 $0x80,到IDT(Interrupt Descriptor Table,中斷描述符表)中找到對應的中斷處理程序的入口地址
  4. 開始執行中斷處理程序
  5. 中斷處理程序根據 eax寄存器中存儲的系統調用號,到 SCT(Systerm call table,系統調用表)中找到sys_fork()的入口地址
  6. 執行 sys_fork 系統調用

明白了整個系統調用的流程後,我們就可以通過嵌入式彙編直接調用想調用的系統調用了,具體流程如下:

  1. 查詢相應的系統調用號
  2. 將系統調用號保存到 eax寄存器中
  3. 通過 int $0x80指令自陷
  4. 函數調用完成,自動將結果(返回值)保存在 eax 寄存器中
  5. eax 寄存器的內容進行輸出

整體的流程相當於把函數庫中的工作實現了一遍。

現在以 getpid爲例,分別用C函數庫和嵌入式彙編(查看嵌入式彙編相關知識)實現其系統調用:
(getpid的系統調用號是 20點這裏查看完整的系統調用列表

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
    printf("pid is %d\n",getpid());  

    int pidAsm = 0;
    asm volatile(
            "mov $0, %%ebx\n\t"   //系統調用第一個參數,清零,不清零好像也沒影響
            "mov $20, %%eax\n\t"  //保存系統調用號
            "int $0x80\n\t"    //自陷
            "mov %%eax, %0\n\t"  //將結果保存到變量 pidAsm中
            : "=m"(pidAsm)
            );
    printf("using asm,pid is %d\n", pidAsm);
}

運行結果如下:

運行結果

可以看到,兩種方式得到的結果是一樣的,這也印證了我們的猜想。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章