成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

系統調用與函數調用有什么區別?

開發 前端
如果我們編寫的代碼可以直接調用所有的操作系統函數那么從某種程度上講的確可以說是能控制操作系統,但如果操作系統只允許你調用內核中的有限的幾個函數呢?

?大家新年好,我是小風哥,這是今年的第一篇技術文,我們來聊聊系統調用與普通的函數調用之間的區別。

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

void funcB()}
void funcA() funcB();}

函數之間是可以相互調用的,這很簡單很happy有沒有。

要知道是代碼、是函數就可以相互調用,不管你用什么語言寫的。

假設funcB是內核中的函數,funcA是你自己寫的函數,就像這樣:

// Linux內核中的函數void funcB()}
// 你的函數void funcA() funcB();}

那么funcA應該也能調用funcB(如果funcB可以供外界調用的話)。

有的同學可能會驚呼,我們可以自己編寫代碼調用操作系統的函數,那豈不是可以直接控制操作系統了?

too yong too simple!

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

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

你又會問,操作系統是怎樣限制應用程序能調用哪些內核中的函數呢?

實際上單靠操作系統這種軟件是沒有辦法限制應用程序能調用哪些以及多少個內核函數的,因此為施加這種限制必須依靠——硬件。

這里的硬件指的就是CPU。

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

我們先來看看普通的函數調用,函數調用對應的機器指令是call指令,就像這樣:

call 0x400410

call指令后的這個地址0x400410就是被調函數的第一條機器指令所在的內存地址。

當CPU執行到這條機器指令時直接跳轉到對應的地址繼續執行指令,從程序員的角度看就是函數調用。

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

使用syscall指令調用操作系統函數時也是把相應函數的第一條指令的地址放到syscall之后嗎?

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

可以看到,利用這種機制操作系統限制了應用程序可以調用哪些內核中的函數。

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

call 0x400410

這里假設0x400410這個地址指向了一個內核函數地址。

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

這里列舉了Linux在各種處理器上怎樣進行系統調用。

圖片

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

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

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

可以看到,當在普通程序中進行函數調用時就是函數調用,而普通函數調用操作系統中的函數時才叫系統調用。

最后再說一點,普通的函數調用所使用的棧全部位于進程的棧區,假設main函數調用funcA函數,funcA調用funcB函數,那么此時的進程內存布局就像這樣:

圖片

而進行系統調用時當CPU開始執行操作系統的代碼時不再基于進程棧區而是會跳轉到操作系統某個特定內存區域,該區域作為進程在內核中的棧區,因此也叫做內核棧,每個進程在內核中都有自己的內核棧,因此我們可以看到一個進程其實有兩個棧區,一個在用戶態一個在內核態。

假設main函數調用funcA,funcA進行系統調用,調用內核中的funcB函數,funcB函數調用內核中的funcC函數,那么此時的內存布局就像這樣:

圖片

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

責任編輯:武曉燕 來源: 碼農的荒島求生
相關推薦

2023-10-13 15:48:17

OT系統

2020-12-22 13:46:48

APISKD

2011-08-08 14:09:55

dhcpbootp

2018-07-13 17:05:22

SQLMySQL數據庫

2020-09-06 09:51:57

SNMP TrapSyslog網絡協議

2019-02-27 15:22:15

混合云云計算多云

2021-05-16 15:28:59

沙箱容器惡意軟件

2021-06-17 08:19:37

操作系統OS Kernel

2024-01-02 08:21:00

LinuxUbuntu操作系統

2013-07-30 13:35:12

methodfunction

2024-06-24 21:24:12

云計算云網絡

2022-09-14 09:45:15

指標標簽

2012-07-25 15:45:28

ERPSCM

2022-11-22 10:21:23

5GLTE

2024-02-21 14:37:56

2014-11-26 17:42:00

亞馬遜互聯網阿里巴巴

2020-07-13 23:39:16

物聯網IoT萬物互聯

2021-01-13 09:27:31

微服務API分布式

2023-06-27 14:49:34

數據中心IT 設備

2021-12-27 06:57:40

This SuperJava
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一区二区三区在线免费观看 | 欧美精品久久久久久久久老牛影院 | 91精品国产欧美一区二区 | 久久亚洲国产精品日日av夜夜 | 国产精品久久久久久久久久久久冷 | 精品久久久久久久久久久久久 | 完全免费在线视频 | 久久久精品网 | 亚洲91精品 | 国产成人精品久久二区二区91 | 亚洲 中文 欧美 日韩 在线观看 | 成人国产一区二区三区精品麻豆 | 丁香综合| 91麻豆精品国产91久久久更新资源速度超快 | 亚洲网在线 | 国产91久久久久久久免费 | 欧美一区二不卡视频 | 中文字幕在线观看 | 久久久成人精品 | 国产成人综合在线 | 亚洲国产成人精品一区二区 | av中文在线观看 | 国产精品美女在线观看 | 欧美极品在线观看 | 免费在线国产视频 | 九九福利 | 蜜臀久久99精品久久久久野外 | 国产一区欧美一区 | 亚洲国产精品久久人人爱 | 精品久久久久一区二区国产 | 天天操操 | av日日操| 色婷婷综合网 | 一区二区三区四区不卡视频 | 性一区 | 精品一区av | 国产福利91精品 | 中文字幕不卡在线观看 | 久久成人国产 | 神马九九 | 97成人免费 |