我們來聊聊系統調用與普通的函數調用之間的區別。
作為程序員你肯定寫過無數的函數,假設有這樣兩個函數:
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函數,那么此時的內存布局就像這樣:
好啦,這個話題就到這里,希望對大家理解操作系統有所幫助。
-
函數
+關注
關注
3文章
4327瀏覽量
62573 -
代碼
+關注
關注
30文章
4779瀏覽量
68525 -
系統調用
+關注
關注
0文章
28瀏覽量
8324
發布評論請先 登錄
相關推薦
評論