自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入理解Linux系統(tǒng)調(diào)用

系統(tǒng) Linux
這樣當(dāng)CPU執(zhí)行syscall執(zhí)行時就會跳轉(zhuǎn)到Linux內(nèi)核中的write函數(shù),同時在執(zhí)行該函數(shù)時也能知道write函數(shù)所需要的參數(shù)是什么。?

?大家好,我是小風(fēng)哥。

在前兩篇文章《為什么計算機需要操作系統(tǒng)?》《??系統(tǒng)調(diào)用與函數(shù)調(diào)用有什么區(qū)別??》中我們了解了什么是系統(tǒng)調(diào)用、為什么需要系統(tǒng)調(diào)用、系統(tǒng)調(diào)用與函數(shù)調(diào)用有什么區(qū)別,那么在今天的文章中我們從理論來到現(xiàn)實,看看Linux中的系統(tǒng)調(diào)用是怎樣實現(xiàn)的。

首先我們先來簡單復(fù)習(xí)下之前講解過的知識。

系統(tǒng)調(diào)用和普通的函數(shù)調(diào)用沒有本質(zhì)區(qū)別,普通的函數(shù)調(diào)用一般調(diào)用的是我們自己編寫的函數(shù)或者其它庫函數(shù),而系統(tǒng)調(diào)用調(diào)用的則是內(nèi)核中的函數(shù),更學(xué)術(shù)一點的說法是這樣的,所謂系統(tǒng)調(diào)用是指用戶態(tài)程序請求操作系統(tǒng)提供的服務(wù)。

一提到服務(wù),大家最先想到的一定是服務(wù)器,假設(shè)客戶端是瀏覽器,瀏覽器發(fā)送http請求,服務(wù)器接收到請求后進行解析然后調(diào)用相應(yīng)的hander,從本質(zhì)上講就是客戶端觸發(fā)了服務(wù)器端的某個函數(shù)的運行,這時我們說客戶端請求了服務(wù)器端上的服務(wù)。

而系統(tǒng)調(diào)用與此類似,只不過用戶態(tài)程序并不是通過http觸發(fā)了操作系統(tǒng)中某個函數(shù)的運行,而是通過機器指令來觸發(fā)的,因為用戶態(tài)的App和操作系統(tǒng)運行在同一臺計算機系統(tǒng)上,而客戶端和服務(wù)器端運行在不同的計算機系統(tǒng)中(絕大部分情況下),因此客戶端只能通過網(wǎng)絡(luò)協(xié)議http來與服務(wù)器進行通信。

圖片

更通俗的說法就是所謂系統(tǒng)調(diào)用是指用戶態(tài)的某個函數(shù)調(diào)用內(nèi)核中的某個函數(shù)。

接下來我們用一段簡單的hello world程序看下系統(tǒng)調(diào)用,這段程序需要運行在x86_64下:

.datamsg:    .ascii "Hello, world!\n"    len = . - msg.text    .global _start_start:    movq  $1, %rax    movq  $1, %rdi    movq  $msg, %rsi    movq  $len, %rdxsyscall    movq  $60, %rax    xorq  %rdi, %rdisyscall

使用以下命令編譯:

$ gcc -c test.S
$ ld -o test test.o

然后執(zhí)行:

./test
Hello, world!

這段匯編代碼成功的打印出了hello world,這段代碼是什么意思呢?

注意看.data這一段,這里說的是程序定義了哪些數(shù)據(jù),.text段是說程序中包含了哪些執(zhí)行,我們之前提到進程的內(nèi)存布局時總是說數(shù)據(jù)段以及代碼段,這里的數(shù)據(jù)段指的就是匯編中的.data段、代碼段指的就是匯編中的.text段,現(xiàn)在你應(yīng)該明白了吧。

圖片

在.text段我們看到了一條略顯奇怪的指令,syscall,這條指令是什么意思呢?

我們來翻看一下intel的開發(fā)手冊:

SYSCALL invokes an OS system-call handler at privilege level 0. It does so by loading RIP from the IA32_LSTAR MSR (after saving the address of the instruction following SYSCALL into RCX). (The WRMSR instruction ensures that the IA32_LSTAR MSR always contain a canonical address.)

這段話告訴我們intel處理器在執(zhí)行syscall指令時會在內(nèi)核態(tài)調(diào)用操作系統(tǒng)的某個函數(shù),即syscall-call handler,這個過程就是所謂的系統(tǒng)調(diào)用,我們知道CPU執(zhí)行某個函數(shù)時必須知道某個函數(shù)在內(nèi)存中的地址,那么CPU是怎么知道某個syscall-call handler的內(nèi)存地址呢?

原來syscall-call handler所在的內(nèi)存地址存儲在寄存器MSR中,那么又是誰將這個地址存儲在了寄存器MSR中呢?很顯然是操作系統(tǒng),接下來以Linux為例來講解。

Linux內(nèi)核初始化時將syscall-call handler也就是Linux內(nèi)核中entry_SYSCALL_64函數(shù)的地址寫入寄存器MSR中:

wrmsrl(MSR_LSTAR, entry_SYSCALL_64);

其中syscall-call handler也就是entry_SYSCALL_64定義在了Linux源碼中的arch/x86/entry/entry_64.S,上述初始化寄存器MSR的代碼定義在了arch/x86/kernel/cpu/common.c。

現(xiàn)在我們知道了,當(dāng)CPU執(zhí)行syscall時會無腦跳轉(zhuǎn)到寄存器MSR中保存的函數(shù)地址,也就是entry_SYSCALL_64函數(shù),那么很顯然的,所有系統(tǒng)調(diào)用的入口都是entry_SYSCALL_64函數(shù),那么操作系統(tǒng)該怎么區(qū)分到底是調(diào)用的read系統(tǒng)調(diào)用還是write等系統(tǒng)調(diào)用?

原來,操作系統(tǒng)中給每種系統(tǒng)調(diào)用分配了一個序號,就像Linux中這樣:

0  common  read      sys_read
1 common write sys_write
2 common open sys_open
3 common close sys_close
4 common stat sys_newstat
5 common fstat sys_newfstat
6 common lstat sys_newlstat
7 common poll sys_poll
8 common lseek sys_lseek
9 common mmap sys_mmap
...

可以看到,0號系統(tǒng)調(diào)用表示的是內(nèi)核中的read函數(shù),1號系統(tǒng)調(diào)用表示的內(nèi)核中的write函數(shù),在進行系統(tǒng)調(diào)用時會將表示系統(tǒng)調(diào)用類別的序號寫入通用寄存器中。

從上面這個表格中可以看到write系統(tǒng)調(diào)用的序號是1,因此在hello world程序中我們將1寫入寄存器rax中:

movq  $1, %rax

這條指令就表示我們將要調(diào)用第1號系統(tǒng)調(diào)用,也就是sys_write,hello world程序中后續(xù)三條機器指令的函數(shù)是:

# 寫入文件描述符1
movq $1, %rdi


# 保存指向字符串的指針
movq $msg, %rsi


# 寫入數(shù)據(jù)的大小
movq $len, %rdx

實際上這四條機器指令都是為執(zhí)行syscall進行的鋪墊,也就是執(zhí)行syscall所需要的參數(shù),可以看到我們進行系統(tǒng)調(diào)用傳遞參數(shù)時都是通過寄存器來完成的。

這樣當(dāng)CPU執(zhí)行syscall執(zhí)行時就會跳轉(zhuǎn)到Linux內(nèi)核中的write函數(shù),同時在執(zhí)行該函數(shù)時也能知道write函數(shù)所需要的參數(shù)是什么。?

責(zé)任編輯:武曉燕 來源: 碼農(nóng)的荒島求生
相關(guān)推薦

2023-09-18 11:34:17

Linux系統(tǒng)

2022-11-09 08:12:07

2022-09-01 08:08:35

Android移動操作系統(tǒng)

2013-06-20 10:25:56

2021-08-31 10:32:11

LinuxPage Cache命令

2018-04-16 11:04:23

HBaseRegion Serv數(shù)據(jù)庫

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數(shù)據(jù)結(jié)構(gòu)hash函數(shù)

2020-07-21 08:26:08

SpringSecurity過濾器

2018-09-12 15:48:35

ext4Linux文件系統(tǒng)

2017-01-12 19:34:58

2021-05-19 07:56:26

Linux內(nèi)核搶占

2021-05-31 07:50:59

Linux文件系統(tǒng)

2020-09-23 10:00:26

Redis數(shù)據(jù)庫命令

2017-01-10 08:48:21

2017-08-15 13:05:58

Serverless架構(gòu)開發(fā)運維

2019-06-25 10:32:19

UDP編程通信

2024-02-21 21:14:20

編程語言開發(fā)Golang

2022-04-21 14:09:17

lsofLinux虛擬文件

2013-09-22 14:57:19

AtWood
點贊
收藏

51CTO技術(shù)棧公眾號