Syscall系統呼叫Linux核心跟蹤

2021-06-08 17:56:43 字數 2831 閱讀 6747

在linux的使用者空間,我們經常會呼叫系統呼叫,下面我們跟蹤一下read系統呼叫,使用的linux核心版本為linux2.6.37。不同的linux版本其中的實現略有不同。

在一些應用中我們可以看到下面的一些定義:

#define real_read(fd, buf, count ) (syscall(sys_read, (fd), (buf), (count)))

其實真正呼叫的還是系統函式syscall(sys_read),也就是sys_read()函式中,在linux2.6.37中的利用幾個巨集定義實現。

linux 系統呼叫(sci,system call inte***ce)的實現機制實際上是乙個多路匯聚以及分解的過程,該匯聚點就是 0x80 中斷這個入口點(x86 系統結構)。也就是說,所有系統呼叫都從使用者空間中匯聚到 0x80 中斷點,同時儲存具體的系統呼叫號。當 0x80 中斷處理程式執行時,將根據系統呼叫號對不同的系統呼叫分別處理(呼叫不同的核心函式處理)。

引起系統呼叫的兩種途徑

(1)int $0×80 , 老式linux核心版本中引起系統呼叫的唯一方式

(2)sysenter彙編指令

在linux核心中使用下面的巨集進行系統呼叫

syscall_define3(read, unsigned int, fd, char __user *, buf, size_t, count)

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 = ; \

static const char *args_##sname = ; \

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__)

#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__)) \

\syscall_alias(sys##name, sys##name); \

static inline long sysc##name(__sc_decl##x(__va_args__))

#define syscall_define(name) asmlinkage long sys_##name

#define __syscall_definex(x, name, ...) \

asmlinkage long sys##name(__sc_decl##x(__va_args__))

最終會呼叫下面型別的巨集定義:

asmlinkage long sys##name(__sc_decl##x(__va_args__))

也就是我們前面提到的sys_read()系統函式。

也就是巨集定義中的下面**:

struct file *file;

ssize_t ret = -ebadf;

int fput_needed;

file = fget_light(fd, &fput_needed);

if (file)

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 檔案系統層

Linux系統呼叫 syscall 原理

linux體系結構 核心空間與使用者空間是程式執行的兩種不同狀態,通過系統呼叫和硬體中斷能夠完成從使用者空間到核心空間的轉移。如下圖所示 linux 體系結構圖 從上圖得知,linux由使用者空間和核心空間 一般情況下,使用者程序是不能訪問核心的。它既不能訪問核心所在的記憶體空間,也不能呼叫核心中的...

Linux系統呼叫 使用syscall

博主的另一篇博文介紹了如何使用int 0x80指令進行linux系統呼叫,這一篇博文介紹一下如何使用另一種方式 syscall指令進行linux系統呼叫,然後會簡要說明二者的不同。通過syscall指令進行linux系統呼叫與通過int 0x80指令進行linux系統呼叫在使用上差別不大,系統呼叫號...

Syscall系統呼叫Linux核心跟蹤

在linux的使用者空間,我們經常會呼叫系統呼叫,下面我們跟蹤一下read系統呼叫,使用的linux核心版本為linux2.6.37。不同的linux版本其中的實現略有不同。在一些應用中我們可以看到下面的一些定義 define real read fd,buf,count syscall sys r...