0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux中的系統(tǒng)調(diào)用是怎樣實(shí)現(xiàn)

jf_78858299 ? 來(lái)源:碼農(nóng)的荒島求生 ? 作者:碼農(nóng)的荒島求生 ? 2023-02-15 11:40 ? 次閱讀

那么在今天的文章中我們從理論來(lái)到現(xiàn)實(shí),看看Linux中的系統(tǒng)調(diào)用是怎樣實(shí)現(xiàn)的。

首先我們先來(lái)簡(jiǎn)單復(fù)習(xí)下之前講解過(guò)的知識(shí)。

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

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

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

圖片

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

接下來(lái)我們用一段簡(jiǎn)單的hello world程序看下系統(tǒng)調(diào)用,這段程序需要運(yùn)行在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í)行:

./testHello, world!

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

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

圖片

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

我們來(lái)翻看一下intel的開發(fā)手冊(cè):

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指令時(shí)會(huì)在內(nèi)核態(tài)調(diào)用操作系統(tǒng)的某個(gè)函數(shù),即syscall-call handler,這個(gè)過(guò)程就是所謂的系統(tǒng)調(diào)用,我們知道CPU執(zhí)行某個(gè)函數(shù)時(shí)必須知道某個(gè)函數(shù)在內(nèi)存中的地址,那么CPU是怎么知道某個(gè)syscall-call handler的內(nèi)存地址呢?

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

Linux內(nèi)核初始化時(shí)將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時(shí)會(huì)無(wú)腦跳轉(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)用?

原來(lái),操作系統(tǒng)中給每種系統(tǒng)調(diào)用分配了一個(gè)序號(hà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號(hào)系統(tǒng)調(diào)用表示的是內(nèi)核中的read函數(shù),1號(hào)系統(tǒng)調(diào)用表示的內(nèi)核中的write函數(shù),在進(jìn)行系統(tǒng)調(diào)用時(shí)會(huì)將表示系統(tǒng)調(diào)用類別的序號(hào)寫入通用寄存器中。

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

movq  $1, %rax

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

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


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


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

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

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

好啦,這篇就到這里,最后,我準(zhǔn)備開通知識(shí)星球啦,我會(huì)把所有文章中留下的問(wèn)題總結(jié)在這里,同時(shí)也鼓勵(lì)大家在這里輸出自己的深度、系統(tǒng)性的思考,沉淀出屬于自己的知識(shí)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209540
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4331

    瀏覽量

    62633
  • 系統(tǒng)調(diào)用

    關(guān)注

    0

    文章

    28

    瀏覽量

    8328
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux系統(tǒng)調(diào)用實(shí)現(xiàn)與應(yīng)用

    在計(jì)算機(jī)科學(xué),系統(tǒng)調(diào)用(System Call)是一種操作系統(tǒng)提供的服務(wù),它允許應(yīng)用程序通過(guò)軟件中斷的方式訪問(wèn)操作系統(tǒng)內(nèi)核
    發(fā)表于 06-14 11:46 ?534次閱讀

    Linux內(nèi)核系統(tǒng)調(diào)用詳解

    Linux內(nèi)核設(shè)置了一組用于實(shí)現(xiàn)各種系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用。用戶可以通過(guò)
    發(fā)表于 08-23 10:37 ?793次閱讀
    <b class='flag-5'>Linux</b>內(nèi)核<b class='flag-5'>中</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>詳解

    ARM Linux系統(tǒng)調(diào)用是如何實(shí)現(xiàn)的呢

    和執(zhí)行程序。Unix系統(tǒng)通過(guò)向內(nèi)核發(fā)出系統(tǒng)調(diào)用(system call)實(shí)現(xiàn)了用戶態(tài)進(jìn)程和硬件設(shè)備之間的大部分接口。系統(tǒng)
    發(fā)表于 05-06 10:42

    ARM linux系統(tǒng)調(diào)用實(shí)現(xiàn)原理

    大家都知道linux的應(yīng)用程序要想訪問(wèn)內(nèi)核必須使用系統(tǒng)調(diào)用從而實(shí)現(xiàn)從usr模式轉(zhuǎn)到svc模式。下面咱們看看它的實(shí)現(xiàn)過(guò)程。
    發(fā)表于 05-30 11:24 ?2237次閱讀

    基于linux系統(tǒng)實(shí)現(xiàn)的vivado調(diào)用VCS仿真教程

    VCS-MX的版本,可以混合編譯Verilog和VHDL語(yǔ)言 由于在linux系統(tǒng)個(gè)人用戶各種權(quán)限被限制,導(dǎo)致很多地方無(wú)法正常使用軟件之間的協(xié)調(diào)工作。 為了以防萬(wàn)一,在此以個(gè)人用戶去實(shí)現(xiàn)
    的頭像 發(fā)表于 07-05 03:30 ?1.1w次閱讀
    基于<b class='flag-5'>linux</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>實(shí)現(xiàn)</b>的vivado<b class='flag-5'>調(diào)用</b>VCS仿真教程

    透了解系統(tǒng)調(diào)用助你成為Linux下編程高手

    Linux內(nèi)核設(shè)置了一組用于實(shí)現(xiàn)各種系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用。用戶可以通過(guò)
    的頭像 發(fā)表于 05-11 11:27 ?3433次閱讀
    透了解<b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>助你成為<b class='flag-5'>Linux</b>下編程高手

    你知道Linux系統(tǒng)調(diào)用的原理

    系統(tǒng)調(diào)用是應(yīng)用程序與操作系統(tǒng)內(nèi)核之間的接口,它決定了程序如何與內(nèi)核打交道的。無(wú)論程序是直接進(jìn)行系統(tǒng)調(diào)用,還是通過(guò)運(yùn)行庫(kù),最終還是會(huì)到達(dá)
    發(fā)表于 05-16 16:21 ?1499次閱讀
    你知道<b class='flag-5'>Linux</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>的原理

    Linux系統(tǒng)調(diào)用的技巧

    1.linux系統(tǒng)調(diào)用的基本原理  linux系統(tǒng)調(diào)用形式與POSIX兼容,也
    發(fā)表于 04-02 14:36 ?393次閱讀

    Linux系統(tǒng)調(diào)用是什么

    所謂系統(tǒng)調(diào)用是指操作系統(tǒng)提供給用戶程序調(diào)用的一組“特殊”接口,用戶程序可以通過(guò)這組“特殊”接口獲得操作系統(tǒng)內(nèi)核提供的服務(wù)。例如,用戶可以通過(guò)
    發(fā)表于 06-11 09:33 ?2357次閱讀

    系統(tǒng)調(diào)用是如何實(shí)現(xiàn)的?

    這張圖畫了挺久的,主要是想讓大家可以從全局角度,看下linux內(nèi)核系統(tǒng)調(diào)用實(shí)現(xiàn)。 在講具體的細(xì)節(jié)之前,我們先根據(jù)上圖,從整體上看一下
    的頭像 發(fā)表于 02-20 16:46 ?3987次閱讀
    <b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用是</b>如何<b class='flag-5'>實(shí)現(xiàn)</b>的?

    關(guān)于Linux內(nèi)核系統(tǒng)調(diào)用是如何實(shí)現(xiàn)的與結(jié)果

    在執(zhí)行 entry_SYSCALL_64 函數(shù)時(shí),內(nèi)核代碼會(huì)根據(jù)約定,先從rax寄存器獲取想要執(zhí)行的系統(tǒng)調(diào)用的編號(hào),然后根據(jù)該編號(hào)從sys_call_table數(shù)組中找到對(duì)應(yīng)的系統(tǒng)
    的頭像 發(fā)表于 03-19 10:52 ?1570次閱讀

    如何區(qū)分xenomai、linux系統(tǒng)調(diào)用/服務(wù)

    對(duì)于同一個(gè)POSIX接口應(yīng)用程序,可能既需要xenomai內(nèi)核提供服務(wù)(xenomai 系統(tǒng)調(diào)用),又需要調(diào)用linux內(nèi)核提供服務(wù)(linux
    的頭像 發(fā)表于 05-10 10:28 ?2076次閱讀

    Linux內(nèi)核系統(tǒng)調(diào)用概述及實(shí)現(xiàn)原理

    本文介紹了系統(tǒng)調(diào)用的一些實(shí)現(xiàn)細(xì)節(jié)。首先分析了系統(tǒng)調(diào)用的意義,它們與庫(kù)函數(shù)和應(yīng)用程序接口(API)有怎樣
    的頭像 發(fā)表于 05-14 14:11 ?2221次閱讀
    <b class='flag-5'>Linux</b>內(nèi)核<b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>概述及<b class='flag-5'>實(shí)現(xiàn)</b>原理

    Linux系統(tǒng)調(diào)用的具體實(shí)現(xiàn)原理

    文我將基于 ARM 體系結(jié)構(gòu)角度,從 Linux 應(yīng)用層例子到內(nèi)核系統(tǒng)調(diào)用函數(shù)的整個(gè)過(guò)程來(lái)梳理一遍,講清楚linux系統(tǒng)
    的頭像 發(fā)表于 09-05 17:16 ?1101次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>的具體<b class='flag-5'>實(shí)現(xiàn)</b>原理

    Linux系統(tǒng)調(diào)用概述

    控制。也就是說(shuō)操作系統(tǒng)是使用這些資源的唯一入口,而這個(gè)入口就是操作系統(tǒng)提供的系統(tǒng)調(diào)用(System Call)。在linux
    的頭像 發(fā)表于 11-09 10:27 ?552次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>概述