Linux核心學習之系統呼叫

2021-06-28 13:41:02 字數 3561 閱讀 6919

文章參考linux核心修煉之道。

1. 系統呼叫概念

大家都知道作業系統的作用是管理計算機的軟硬體資源,但是作業系統要向使用者提供各種各樣的服務,而使用者應用程式訪問這些服務的方式就是通過系統呼叫。但是一般來說,我們都是通過作業系統封裝好的api(應用程式設計介面)來間接使用系統呼叫的。比如在windows程式設計中,你可以呼叫winapi,他以c庫的形式給出。比如在linux當中,我們呼叫的read函式:int read(int handle, void *buf, int nbyte), 我們一般成為我們在使用系統呼叫read,因為相對應標準c函式庫裡面有乙個fread。但是,實際上我們並沒有直接的實現系統呼叫,我們通過系統封裝的read函式去呼叫了read的系統呼叫。因為他們名字相同,是對應的關係,所以我們很容易誤解。但是系統呼叫和封裝的系統api函式並不是一一對應的關係,比如系統的execl、execlp、execle、execv、execvp、execve等都是通過execve系統呼叫來執行乙個可執行檔案的。系統呼叫最終必須有明確的操作,使用者應用程式通過系統呼叫進入核心後,會執行各個系統呼叫對應的核心函式,即系統呼叫的服務例程。比如系統呼叫getpid的服務例程是核心函式sys_getpid。

2.  系統呼叫表

核心提供哪些核心函式是對外可用的呢,換句話說核心提供哪些系統呼叫的服務例程呢?這個在系統呼叫表裡面sys_call_table,他儲存了所有的系統呼叫對應的服務例程的函式位址,在arch/i386/kernel/syscall_table.s檔案中,如下:

[cpp]

view plain

copy

print?

entry(sys_call_table)  

.long

sys_restart_syscall   

/* 0 - old "setup()" system call, used for restarting */

.long

sys_exit  

.long

sys_fork  

.long

sys_read  

.long

sys_write  

.long

sys_open      

/* 5 */

.long

sys_close  

.long

sys_waitpid  

.long

sys_creat  

.long

sys_link  

.long

sys_unlink    

/* 10 */

[cpp]

view plain

copy

print?

...  ...  

可以很清楚的看到,所有的系統呼叫都是遵循一定的命名規範的,即在系統名稱之前加"sys_"字首,比如exit系統呼叫對應的系統服務函式為sys_exit。另外系統總共對外提供的系統呼叫服務是非常有限的,我們可以看到只有兩三百個而已。

3. 系統呼叫號

系統呼叫號是什麼呢?上述的每個系統服務例程都有乙個系統呼叫號,使用者是通過系統呼叫號來呼叫這些服務例程而不是通過系統呼叫的名稱。上述的系統呼叫表儲存了所有系統呼叫的服務例程的位址,系統呼叫的過程就是從系統呼叫表中獲取位址去執行。那麼系統呼叫符合就必然要和系統呼叫號聯絡到一起,這就涉及到另外乙個檔案,在include/asm-i386/unistd.h檔案。

[html]

view plain

copy

print?

#define __nr_restart_syscall      0  

#define __nr_exit         1  

#define __nr_fork         2  

#define __nr_read         3  

#define __nr_write        4  

#define __nr_open         5  

#define __nr_close        6  

#define __nr_waitpid          7  

#define __nr_creat        8  

#define __nr_link         9  

#define __nr_unlink      10  

跟上述的系統呼叫表一比較,發現除了字首乙個是sys_乙個是__nr_外,他們的名稱是一模一樣的,而且關鍵他們的順序也是相同的。不錯,核心就是將系統呼叫號作為下標去獲取系統呼叫表中的系統呼叫服務例程的函式位址的。

4. 系統呼叫服務例程

所有的系統呼叫服務例程集中宣告在include/linux/syscalls.h這個檔案當中,但是他們的定義分布在不同的檔案中。比如getpid系統呼叫,他的系統服務例程sys_getpid在kernel/timer.c檔案中定義:

[html]

view plain

copy

print?

asmlinkage long sys_getpid(void)    

asmlinkage標記的含義是僅從堆疊中獲取該資料,不從暫存器及其他地方獲取。

5. 系統呼叫的使用

(1). 通過呼叫c語言庫封裝函式,比如前面所述的read函式。

(2). 通過syscall函式,原型為int syscall(int number, ...)。

具體可以通過以下getpid的系統呼叫來展示系統呼叫的使用。

[html]

view plain

copy

print?

#include 

<

unistd.h

>

#include <

sys/syscall.h

>

#include <

sys/types.h

>

//可以從系統呼叫號檔案中檢視  

#define __nr_gettid 224  

int main()    

另外大部分的系統呼叫都包含了乙個sys_符號常量的巨集定義來制定呼叫號,所以上述syscall函式也可以採用如下方式:

[html]

view plain

copy

print?

tid= syscall

(sys_gettid);

<

span

style

="font-family: arial, verdana, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); "

>

span

>

6. 為什麼要使用系統呼叫

(1)系統呼叫可以為使用者空間提供訪問硬體資源的統一介面,以至於應用程式不必理會具體硬體訪問操作。比如,讀寫檔案時,應用程式不用去關心磁碟的型別,不用關心是什麼檔案系統,等等。

(2)系統呼叫對系統有保護作用,保證系統的安全性和穩定性。系統呼叫規定了使用者程序進入核心的具體方式。使用者只能通過這種方式安全的進入核心,而不准任意在跳入核心,因而可以保護核心的安全性。

Linux 核心學習 系統呼叫(fork)

昨天花了一天的時間在看linux0.11的核心,當看到main.c中的int 函式的時候被乙個系統呼叫難倒了 其實筆者的c,彙編等基礎並不是很厲害。但是處於某些原因,就入了這個核心的坑,被澆冷水是經常的事情 於是各種資料各種搜尋,但是大家給出的資料都是千篇一律,不是一開始就介紹什麼是系統呼叫,就是沒...

Linux核心學習筆記四 系統呼叫

一 使用者空間和核心空間 linux核心將這4g位元組虛擬位址空間的空間分為兩部分 l 將最高的1g位元組 從虛擬位址0xc0000000到0xffffffff 供核心使用,稱為 核心空間 l 將較低的3g位元組 從虛擬位址 0x00000000到0xbfffffff 供各個程序使用,稱為 使用者空...

Linux核心學習筆記四 系統呼叫

一 使用者空間和核心空間 linux核心將這4g位元組虛擬位址空間的空間分為兩部分 l 將最高的1g位元組 從虛擬位址0xc0000000到0xffffffff 供核心使用,稱為 核心空間 l 將較低的3g位元組 從虛擬位址 0x00000000到0xbfffffff 供各個程序使用,稱為 使用者空...