歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> linux 系統調用如何進入內核模式

linux 系統調用如何進入內核模式

日期:2017/3/3 13:56:18   编辑:Linux技術
linux 系統調用如何進入內核模式
分類: LINUX
原文地址:linux 系統調用如何進入內核模式 作者:szbryan
linux下的系統調用如何從用戶態進入內核態?這個問題一直以來都是模模糊糊,最近閱讀了《程序員的自我修養》第十二章:系統調用與API,終於對此有了一個算是比較清醒和深刻的認識:總結了一下,畫了一個圖大致如下(注:沒有內核態返回內核態流程):

其中x86有兩種方式從用戶態陷入內核態:int 0x80系統調用以及新型的sysenter指令。本文暫且基於經典的int 0x80方式。對於用戶態,地球人都知道我們寫的C程序要調用到glibc庫,與我們所理解的庫調用並沒有多大差異。但是對於glibc庫如何陷入內核態,就需要詳細的了解一下。
首先,glibc對系統調用做了一系列的封裝,典型如fork()函數,比如我們所調用的fork()函數,在glibc中實際上定義的是如下一個宏:
_syscall0(pid_t, fork);
這裡有一系列的__syscallN宏定義,其中的N范圍從0-6,這是因為x86在linux下支持的最多的參數個數為6個。每個宏對應著相應個數的參數。fork()沒有參數,所以是_syscall0。這個宏的參數pid_t是返回值的類型,fork是函數的名字,用於下一步的擴展。其中i386版本的_syscall0宏定義如下:
#define _syscall0(type,name) \
{ long __res; \
__asm__ volatile("int 0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
__syscall_return(type, __res);\
}
這就是采用gcc內聯匯編的形式編寫的_syscall0宏,通過這個宏,可以很明顯的看出來是通過int 0x80方式觸發中斷,進入內核態中斷處理。並指明使用eax來傳遞參數和返回值。而此處的參數就是系統調用號,所以由此可知,觸發中斷進入內核時,所有的系統調用號都是通過eax傳遞,這樣在內核態,想知道是什麼系統調用,直接查詢eax寄存器就可以得到系統調用號了。
進入中斷,查詢中斷號,根據安裝的中斷處理程序就可以得到這是一個系統調用,於是查詢系統調用表,根據eax中傳遞的系統調用號就可以得到對應的系統調用。
內核處理完成之後,最後通過__syscall_return從用戶態返回內核態。當然,返回值還是通過eax傳遞返回的。
至於用戶態和內核態的堆棧的切換,記住其中最重要的一個宏SAVE_ALL,就可以查詢到其中的切換了,此處也就不講述。
Copyright © Linux教程網 All Rights Reserved