Syscall系統呼叫Linux核心追蹤
在Linux使用者空間中,我們常常需要呼叫系統呼叫。下面我們以Linux2.6.37版本為例,追蹤read系統呼叫的實作。不同版本的Linux系統呼叫實作可能會有所不同。
#在一些應用程式中,我們可以看到如下定義:
scssCopy code #define real_read(fd, buf, count ) (syscall(SYS_read, (fd), (buf), (count)))
實際上,真正呼叫的是系統函式syscall(SYS_read),也就是sys_read()函式。在Linux2.6.37版本中,函數是透過幾個巨集定義來實現的。
Linux系統呼叫(SCI,system call interface)其實是一個多路匯聚以及分解的過程,匯聚點是0x80中斷入口點(X86系統結構)。也就是說,所有系統呼叫都從用戶空間匯聚到0x80中斷點,同時保存特定的系統呼叫號碼。當0x80中斷處理程序執行時,將根據系統呼叫號碼對不同的系統呼叫分別處理,即呼叫不同的核心函數進行處理。
造成系統呼叫的途徑有兩種:
(1)int $0×80,這是老式Linux核心版本中造成系統呼叫的唯一方式。
(2)sysenter彙編指令
在Linux核心中,我們可以使用下列巨集定義來進行系統呼叫。
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) { struct file *file; ssize_t ret = -EBADF; int fput_needed; file = fget_light(fd, &fput_needed); if (file) { loff_t pos = file_pos_read(file); ret = vfs_read(file, buf, count, &pos); file_pos_write(file, pos); fput_light(file, fput_needed); } return ret; }
其中SYSCALL_DEFINE3的巨集定義如下:
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
##的意思就是巨集中的字元直接替換,
如果name = read,那麼在巨集中__NR_##name就替換成了__NR_read了。 NR##name是系統呼叫號,##指的是兩次巨集展開.即用實際的系統呼叫名字代替”name”,然後再把__NR…展開.如name == ioctl,則為__NR_ioctl。
#ifdef CONFIG_FTRACE_SYSCALLS #define SYSCALL_DEFINEx(x, sname, ...) \ static const char *types_##sname[] = { \ __SC_STR_TDECL##x(__VA_ARGS__) \ }; \ static const char *args_##sname[] = { \ __SC_STR_ADECL##x(__VA_ARGS__) \ }; \ SYSCALL_METADATA(sname, x); \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) #else #define SYSCALL_DEFINEx(x, sname, ...) \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) #endif
不管是否定義CONFIG_FTRACE_SYSCALLS宏,最終都會執行 下面的這個巨集定義:
__SYSCALL_DEFINEx(x, sname, VA_ARGS)
#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS #define SYSCALL_DEFINE(name) static inline long SYSC_##name #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__)); \ static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__)); \ asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__)) \ { \ __SC_TEST##x(__VA_ARGS__); \ return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__)); \ } \ SYSCALL_ALIAS(sys##name, SyS##name); \ static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__)) #else /* CONFIG_HAVE_SYSCALL_WRAPPERS */ #define SYSCALL_DEFINE(name) asmlinkage long sys_##name #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__)) #endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */
最終會呼叫下面類型的巨集定義:
asmlinkage long sys##name(__SC_DECL##x(VA_ARGS))
也就是我們前面提到的sys_read()系統函數。
asmlinkage通知編譯器僅從堆疊中提取該函數的參數。所有的系統呼叫都需要這個限定詞!這和我們上一篇文章quagga中提到的宏定義,有異曲同工之妙。
也就是巨集定義中的下面程式碼:
struct file *file; ssize_t ret = -EBADF; int fput_needed; file = fget_light(fd, &fput_needed); if (file) { loff_t pos = file_pos_read(file); ret = vfs_read(file, buf, count, &pos); file_pos_write(file, pos); fput_light(file, fput_needed); } return ret;
程式碼解析:
- fget_light() :根據 fd 指定的索引,從目前程序描述符中取出對應的 file 物件(請參閱圖3)。
- 如果找不到指定的 file 對象,則傳回錯誤
- 如果找到了指定的 file 物件:
- 呼叫 file_pos_read() 函數取出此次讀寫檔案的目前位置。
- 呼叫 vfs_read() 執行檔案讀取操作,而這個函數最終呼叫 file->f_op.read() 所指向的函數,程式碼如下:
if (file->f_op->read)
ret = file->f_op->read(file, buf, count, pos);
- 呼叫 file_pos_write() 更新檔案的目前讀寫位置。
- 呼叫 fput_light() 更新檔案的引用計數。
- 最後傳回讀取資料的位元組數。
到此,虛擬檔案系統層所做的處理就完成了,控制權交給了 ext2 檔案系統層。
以上是Syscall系統呼叫Linux核心追蹤的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Linux系統的五個基本組件是:1.內核,2.系統庫,3.系統實用程序,4.圖形用戶界面,5.應用程序。內核管理硬件資源,系統庫提供預編譯函數,系統實用程序用於系統管理,GUI提供可視化交互,應用程序利用這些組件實現功能。

要查看 Git 倉庫地址,請執行以下步驟:1. 打開命令行並導航到倉庫目錄;2. 運行 "git remote -v" 命令;3. 查看輸出中的倉庫名稱及其相應的地址。

雖然 Notepad 無法直接運行 Java 代碼,但可以通過借助其他工具實現:使用命令行編譯器 (javac) 編譯代碼,生成字節碼文件 (filename.class)。使用 Java 解釋器 (java) 解釋字節碼,執行代碼並輸出結果。

在 Sublime 中運行代碼的方法有六種:通過熱鍵、菜單、構建系統、命令行、設置默認構建系統和自定義構建命令,並可通過右鍵單擊項目/文件運行單個文件/項目,構建系統可用性取決於 Sublime Text 的安裝情況。

Linux的主要用途包括:1.服務器操作系統,2.嵌入式系統,3.桌面操作系統,4.開發和測試環境。 Linux在這些領域表現出色,提供了穩定性、安全性和高效的開發工具。

要安裝 Laravel,需依序進行以下步驟:安裝 Composer(適用於 macOS/Linux 和 Windows)安裝 Laravel 安裝器創建新項目啟動服務訪問應用程序(網址:http://127.0.0.1:8000)設置數據庫連接(如果需要)

Visual Studio Code (VSCode) 是一款跨平台、開源且免費的代碼編輯器,由微軟開發。它以輕量、可擴展性和對眾多編程語言的支持而著稱。要安裝 VSCode,請訪問官方網站下載並運行安裝程序。使用 VSCode 時,可以創建新項目、編輯代碼、調試代碼、導航項目、擴展 VSCode 和管理設置。 VSCode 適用於 Windows、macOS 和 Linux,支持多種編程語言,並通過 Marketplace 提供各種擴展。它的優勢包括輕量、可擴展性、廣泛的語言支持、豐富的功能和版
