Linux下簡單的系統呼叫

2021-08-16 03:17:26 字數 2960 閱讀 4314

原創

2023年03月17日 21:31:20

本週是linux系統分析課程的第四周課程,本週主要講linux系統呼叫的過程,具體知識點和實驗結果總結如下。

系統呼叫:系統呼叫只是乙個特殊的中斷。我們通過庫函式和系統呼叫打交道,庫函式把系統呼叫封裝起來。

1、儲備知識——核心態和使用者態

核心態:在高執行級別下,**可以執行特權指令,訪問任意的物理記憶體,這種cpu執行級別就對應著核心態。

使用者態:在使用者態級別下,**的掌控範圍會受到限制,只能在對應級別允許的範圍內活動。

注:intel x86cpu有四種不同的執行級別0-3,linux只使用了其中的0級和3級分別來表示核心態和使用者態。

2、為什麼有許可權級別的劃分?

若沒有使用者態和核心態的劃分,使用者寫的不健壯的程式就可以執行特權指令時,就很容易是系統崩潰。作業系統發展過程中劃分了使用者態和核心態,是系統更穩定的機制。

3、暫存器在系統呼叫中的作用

cs暫存器的最低兩位表明了當前**的特權級。cpu每條指令的讀取都是通過cs:eip這兩個暫存器:其中cs是**段選擇暫存器,eip是偏移量暫存器。

4、記憶體位址空間

一般在linux中,位址空間是乙個顯著的標誌:0xc0000000以上的位址空間只能在核心態下訪問,0x0000000–0xbfffffff的位址空間在兩種狀態下都可以訪問。

注:產生中斷是從使用者態進入核心態的主要方式。

5、暫存器上下文:

5.1從使用者態切換到核心態時:

必須儲存使用者態的暫存器上下文;

同時把核心態的暫存器的值放到暫存器中。

5.2中斷/int指令會在堆疊上儲存一些暫存器的值:

如使用者態棧頂位址;

當前的狀態字;

當時的cs:eip的值。

5.3中斷發生後的第一件事就是儲存現場:

儲存現場:就是進入中斷程式,儲存需要用到的暫存器的資料。

5.4中斷處理結束前最後一件事就是恢復現場:

恢復現場:就是退出中斷程式恢復儲存暫存器的資料。

注:iret指令和中斷訊號(包括int指令)發生時的cpu做的動作整好相反。

如下圖所示

中斷指令interrupt(ex:int 0x80)開始進行系統呼叫;

儲存當前cs:eip,ss:esp,eflags的值到核心堆疊,同時載入了中斷服務程式的位址到cs:eip以及核心堆疊棧頂指標到ss:esp中。int指令完成上述操作過程。

核心**,完成中斷服務:

發生程序排程,則儲存排程時的現場,進行排程,完成排程後再恢復現場;

不發生程序排程,則恢復之前的儲存現場:iret - pop cs:eip/ss:esp/eflags from kernel stack.

注:系統呼叫的三層皮:api,中斷向量,中斷服務程式

5、系統呼叫的服務例程:

5.1 當使用者態程序呼叫乙個系統呼叫時,cpu切換核心態並開始執行乙個核心函式。

在linux中是通過執行int $0x80來執行系統呼叫的,這條彙編指令產生向量為128的程式設計異常;

inter pentium ii中引入了sysenter指令(快速系統呼叫),2,6已經支援。

5.2 傳參:

核心實現了很多不同的系統呼叫;

程序必須指明需要哪個系統呼叫,這需要使用eax暫存器傳遞乙個名為系統呼叫號的引數

5.3 系統呼叫也需要輸入輸出引數,例如:

實際的值;

使用者態程序位址空間的變數的位址;

甚至包含指向使用者態函式的指標的資料結構的位址。

system call是linux中所有系統呼叫的入口點,每個系統呼叫至少有乙個引數,即由eax

5.3 傳遞的系統呼叫號;

系統呼叫號將xyz和sys_xyz關聯起來;用eax暫存器來傳遞引數;

乙個應用程式呼叫fork()封裝例程,那麼在執行int $0x80之前就把eax暫存器的值置為2(即 nr fork);

這個暫存器的設定是libc庫中的封裝例程進行的,因此使用者一般不關心系統呼叫號;

進入sys,call之後,立即將eax的值壓入核心堆疊;

5.4 暫存器引數具有如下限制:

每個引數的長度不能超過暫存器的長度,即32位;

在系統呼叫號(eax)之外,引數的個數不能超過6個(ebx,ecx,edx,esi,edi,ebp)。

實驗過程中呼叫mkdir系統函式,mkdir呼叫號為39,函式原型如下:

int mkdir(const char *path, mode_t mode);

引數:

path是目錄名

mode是目錄許可權

返回值:

返回0 表示成功, 返回 -1表示錯誤,並且會設定errno值。

通過c**呼叫

mkdir.c

#include 

#include

#include

int main()

else

printf("mkdir failed!\n");

return

0;}

通過嵌入式彙編呼叫

通過對系統呼叫的兩種**實現方法的分析,我們可以知道c語言的api只不過是對linux底層系統呼叫的一次封裝而已,本質上是通過系統中斷實現的。

了解linux下的系統呼叫

計算機系統的各種硬體資源是有限的,在現代多工作業系統上同時執行的多個程序都需要訪問這些資源,為了更好的管理這些資源程序是不允許直接操作的,所有對這些資源的訪問都必須有作業系統控制。也就是說作業系統是使用這些資源的唯一入口,而這個入口就是作業系統提供的系統呼叫。系統呼叫是屬於作業系統核心的一部分的,必...

Linux 系統呼叫簡單了解

系統呼叫決定了作業系統是否好用,功能是否齊全。建立程序 fork 原程序叫父程序,新程序叫子程序。當父程序fork建立子程序時,採用寫時拷貝的方案。先是父子共用同一記憶體,如果有一方要寫資料,就會將該記憶體塊進行拷貝。然後再寫。fork可以根據返回值進行對父子程序的區分。子程序可以使用exec函式族...

Linux下select 系統呼叫

一 select 函式功能 select系統呼叫允許程式同時在多個底層檔案表述符上,等待輸入的到達或輸出的完成。二 函式意義 乙個伺服器可以同時在多個開啟的套接字等待請求到來的方法而處理多個客戶。只是具體應用的其中之一 自己的理解,但凡是程式在執行過程中會遇到阻塞 不到條件發生就不往下執行 的情況,...