RM新时代网站-首页

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

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

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

系統(tǒng)調(diào)用與普通的函數(shù)調(diào)用之間的區(qū)別

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

我們來聊聊系統(tǒng)調(diào)用與普通的函數(shù)調(diào)用之間的區(qū)別。

作為程序員你肯定寫過無數(shù)的函數(shù),假設(shè)有這樣兩個函數(shù):

void funcB() {
}


void funcA() {
  funcB();
}

函數(shù)之間是可以相互調(diào)用的,這很簡單很happy有沒有。

要知道是代碼、是函數(shù)就可以相互調(diào)用,不管你用什么語言寫的。

假設(shè)funcB是內(nèi)核中的函數(shù),funcA是你自己寫的函數(shù),就像這樣:

// Linux內(nèi)核中的函數(shù)void funcB() {}
// 你的函數(shù)void funcA() { funcB();}

那么funcA應(yīng)該也能調(diào)用funcB(如果funcB可以供外界調(diào)用的話)。

有的同學(xué)可能會驚呼,我們可以自己編寫代碼調(diào)用操作系統(tǒng)的函數(shù),那豈不是可以直接控制操作系統(tǒng)了?

too yong too simple!

如果我們編寫的代碼可以直接調(diào)用所有的操作系統(tǒng)函數(shù)那么從某種程度上講的確可以說是能控制操作系統(tǒng),但如果操作系統(tǒng)只允許你調(diào)用內(nèi)核中的有限的幾個函數(shù)呢?

怎么樣,你(應(yīng)用程序)是不是就被限制住了。

你又會問,操作系統(tǒng)是怎樣限制應(yīng)用程序能調(diào)用哪些內(nèi)核中的函數(shù)呢?

實際上單靠操作系統(tǒng)這種軟件是沒有辦法限制應(yīng)用程序能調(diào)用哪些以及多少個內(nèi)核函數(shù)的,因此為施加這種限制必須依靠——硬件。

這里的硬件指的就是CPU。

那么CPU又是怎么施加這種限制的呢?

我們先來看看普通的函數(shù)調(diào)用,函數(shù)調(diào)用對應(yīng)的機器指令是call指令,就像這樣:

call 0x400410

call指令后的這個地址0x400410就是被調(diào)函數(shù)的第一條機器指令所在的內(nèi)存地址。

當CPU執(zhí)行到這條機器指令時直接跳轉(zhuǎn)到對應(yīng)的地址繼續(xù)執(zhí)行指令,從程序員的角度看就是函數(shù)調(diào)用。

而如果是我們程序的函數(shù)調(diào)用操作系統(tǒng)的函數(shù)就不允許使用call指令了,而是syscall機器指令(x86_64)。

使用syscall指令調(diào)用操作系統(tǒng)函數(shù)時也是把相應(yīng)函數(shù)的第一條指令的地址放到syscall之后嗎?

顯然不是的,因為操作系統(tǒng)系統(tǒng)代碼和你的代碼都是單獨編譯以及運行的,你根本就不知道操作系統(tǒng)的某個函數(shù)存放在內(nèi)存的什么位置上,也不應(yīng)該讓你知道,因此使用syscall調(diào)用操作系統(tǒng)的函數(shù)時我們只能附加一個序號,比如序號0對應(yīng)操作系統(tǒng)中的A函數(shù)、序號1對應(yīng)操作系統(tǒng)中的B函數(shù)等等,這樣使用syscall指令時只需要將該序號寫入rax寄存器即可,CPU在執(zhí)行syscall指令時通過讀取rax寄存器的值就能知道到底該調(diào)用操作系統(tǒng)中的哪個函數(shù)了。

可以看到,利用這種機制操作系統(tǒng)限制了應(yīng)用程序可以調(diào)用哪些內(nèi)核中的函數(shù)。

有的同學(xué)可能會有疑問,如果一個call指令因為種種原因后面跟上的地址”無意“中指向了一個內(nèi)核函數(shù)的地址,那么CPU執(zhí)行call指令時會怎樣呢?就像這樣:

call 0x400410

這里假設(shè)0x400410這個地址指向了一個內(nèi)核函數(shù)地址。

很簡單,CPU在執(zhí)行這條指令時會判斷出當前進程沒有權(quán)限訪問0x400410這個地址,因此CPU在執(zhí)行這條指令時會產(chǎn)生異常,該進程會被直接kill掉。

這里列舉了Linux在各種處理器上怎樣進行系統(tǒng)調(diào)用。

圖片

看到了吧,syscall和call在使用方法上還是有很大不同的,可以看到call是直接調(diào)用的,也就是說應(yīng)用程序這一層中的函數(shù)調(diào)用是直接調(diào)用的,而syscall其實是間接調(diào)用的,即我們調(diào)用操作系統(tǒng)中的函數(shù)時其實是間接調(diào)用的。

除此之外,CPU在執(zhí)行call指令以及syscall指令時另外一個不同點在于模式的切換。

當CPU執(zhí)行普通函數(shù)時其實是運行在用戶態(tài),user mode,在這種模式下CPU不能執(zhí)行某些特權(quán)指令,這也就意味著我們的程序其實是受限的;而當CPU執(zhí)行syscall開始執(zhí)行操作系統(tǒng)的代碼時會切換到內(nèi)核態(tài),kernel mode,在這種模式下CPU可以執(zhí)行任何特權(quán)指令,不受任何限制,操作系統(tǒng)才是真正的管理計算機的大boss。

可以看到,當在普通程序中進行函數(shù)調(diào)用時就是函數(shù)調(diào)用,而普通函數(shù)調(diào)用操作系統(tǒng)中的函數(shù)時才叫系統(tǒng)調(diào)用。

最后再說一點,普通的函數(shù)調(diào)用所使用的棧全部位于進程的棧區(qū),假設(shè)main函數(shù)調(diào)用funcA函數(shù),funcA調(diào)用funcB函數(shù),那么此時的進程內(nèi)存布局就像這樣:

圖片

而進行系統(tǒng)調(diào)用時當CPU開始執(zhí)行操作系統(tǒng)的代碼時不再基于進程棧區(qū)而是會跳轉(zhuǎn)到操作系統(tǒng)某個特定內(nèi)存區(qū)域,該區(qū)域作為進程在內(nèi)核中的棧區(qū),因此也叫做內(nèi)核棧,每個進程在內(nèi)核中都有自己的內(nèi)核棧,因此我們可以看到一個進程其實有兩個棧區(qū),一個在用戶態(tài)一個在內(nèi)核態(tài)。

假設(shè)main函數(shù)調(diào)用funcA,funcA進行系統(tǒng)調(diào)用,調(diào)用內(nèi)核中的funcB函數(shù),funcB函數(shù)調(diào)用內(nèi)核中的funcC函數(shù),那么此時的內(nèi)存布局就像這樣:

圖片

好啦,這個話題就到這里,希望對大家理解操作系統(tǒng)有所幫助。

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

    關(guān)注

    3

    文章

    4327

    瀏覽量

    62569
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4779

    瀏覽量

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

    關(guān)注

    0

    文章

    28

    瀏覽量

    8324
收藏 人收藏

    評論

    相關(guān)推薦

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

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

    如何查看及更改函數(shù)/函數(shù)塊的調(diào)用環(huán)境

    模塊化設(shè)計的思想是把一些相似的功能(比如電機控制、閥控制)設(shè)計成函數(shù)函數(shù)塊,這樣就可以反復(fù)調(diào)用。其優(yōu)點是:使程序架構(gòu)更加清晰,避免重復(fù)編寫相似功能的代碼。不過可能會產(chǎn)生一個疑惑:既然PLC的程序
    的頭像 發(fā)表于 11-17 09:08 ?938次閱讀
    如何查看及更改<b class='flag-5'>函數(shù)</b>/<b class='flag-5'>函數(shù)</b>塊的<b class='flag-5'>調(diào)用</b>環(huán)境

    linux內(nèi)核系統(tǒng)調(diào)用之參數(shù)傳遞

    普通函數(shù)一樣,系統(tǒng)調(diào)用通常需要一些輸入/輸出參數(shù),這些參數(shù)可能包括實際值(即數(shù)字)、用戶模式進程地址空間中的變量地址,甚至包括指向用戶模式函數(shù)
    的頭像 發(fā)表于 12-20 09:32 ?1607次閱讀

    如何確保在調(diào)用之間保留它的值?

    大家好。一個非常基本的問題讓我困惑。一個變量在ISR()文件和3個非中斷文件中更新(讀和寫),并且我希望它的生存期延長,這意味著它在函數(shù)/文件調(diào)用之間保留它的值。它將被限定為“volatile”。但是,它是否還需要具備“靜態(tài)”的資格呢?如何確保在
    發(fā)表于 03-31 07:48

    C++教程之函數(shù)的遞歸調(diào)用

    C++教程之函數(shù)的遞歸調(diào)用 在執(zhí)行函數(shù) f 的過程中,又要調(diào)用 f 函數(shù)本身,稱為函數(shù)的遞歸
    發(fā)表于 05-15 18:00 ?35次下載

    系統(tǒng)調(diào)用函數(shù)庫分析及實例

    作為用戶我們極少接觸系統(tǒng)調(diào)用,但是我們熟悉C 語言,對庫函數(shù)調(diào)用并不陌生。C語言支持一系列庫函數(shù)調(diào)用
    發(fā)表于 06-23 16:46 ?46次下載
    <b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b><b class='flag-5'>函數(shù)</b>庫分析及實例

    類成員函數(shù)普通函數(shù)區(qū)別研究

    本文的目的是研究類成員函數(shù)普通函數(shù)區(qū)別,以及不同調(diào)用方式之間
    發(fā)表于 09-15 14:52 ?32次下載

    詳解python普通函數(shù)創(chuàng)建與調(diào)用

    函數(shù)是一種僅在調(diào)用時運行的代碼塊。您可以將數(shù)據(jù)(稱為參數(shù))傳遞到函數(shù)中,然后由函數(shù)可以把數(shù)據(jù)作為結(jié)果返回。
    的頭像 發(fā)表于 03-01 16:32 ?1856次閱讀

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

    系統(tǒng)調(diào)用普通函數(shù)調(diào)用沒有本質(zhì)區(qū)別,普通
    的頭像 發(fā)表于 02-15 11:40 ?1238次閱讀
    Linux中的<b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>是怎樣實現(xiàn)

    C語言函數(shù)調(diào)用的形式及過程

    C語言函數(shù)調(diào)用時的數(shù)據(jù)傳遞 在調(diào)用有參函數(shù)時,主調(diào)函數(shù)和被調(diào)函數(shù)
    的頭像 發(fā)表于 03-10 14:28 ?1733次閱讀

    什么是函數(shù)調(diào)用?

    函數(shù)調(diào)用,就是使用我們已經(jīng)定義好的函數(shù),或者C語言自帶的庫函數(shù)
    的頭像 發(fā)表于 04-04 17:21 ?5811次閱讀

    SCL中調(diào)用函數(shù)的示例

    在此,可插入函數(shù) (FC) 調(diào)用函數(shù)塊 (FB) 調(diào)用。函數(shù)塊可作為單實例、多重實例或參數(shù)實例進行調(diào)用
    的頭像 發(fā)表于 06-06 10:18 ?2182次閱讀

    網(wǎng)絡(luò)系統(tǒng)調(diào)用網(wǎng)絡(luò)套接字入口函數(shù)

    網(wǎng)絡(luò)套接字入口函數(shù) //所有的網(wǎng)絡(luò)套接字系統(tǒng)調(diào)用函數(shù)(socket bind listen connect )都使用一個共同的入口函數(shù):sy
    的頭像 發(fā)表于 07-24 11:02 ?470次閱讀

    python定義函數(shù)調(diào)用函數(shù)的順序

    定義函數(shù)調(diào)用函數(shù)的順序 函數(shù)被定義后,本身是不會自動執(zhí)行的,只有在被調(diào)用后,函數(shù)才會被執(zhí)行,得
    的頭像 發(fā)表于 10-04 17:17 ?1380次閱讀

    python函數(shù)函數(shù)之間調(diào)用

    函數(shù)函數(shù)之間調(diào)用 3.1 第一種情況 程序代碼如下: def x ( f ): def y (): print ( 1 ) return y def f (): print ( 2
    的頭像 發(fā)表于 10-04 17:17 ?587次閱讀
    RM新时代网站-首页