1.什麼是系統調用?
操作系統提供的一個函數調用,就是操作系統給上層應用提供的一個接口。比如open、write、read。上層應用程序通過調用這些函數進入操作系統,使用操作系統的功能。就好像插座一樣,插上去就比較簡單。但是表面上是這些函數,那麼背後是什麼?
2.為什麼要引入系統調用?
問題:
實現一個whoami系統調用。
■用戶程序調用whoami,一個字符串“yang”放在操作系統中,取出來打印
直觀思想:
操作系統在內存中,應用程序也在內存中,既然都在內存中,為什麼不直接jmp或者mov?
■不能隨意地調用數據,不能隨意地jmp。
■例如可以直接看到root密碼,然後可以修改它。
這樣的活,操作系統太不安全了。
怎麼樣設置不能jmp的?
通過檢查CPL和DPL
既然不能jmp也不能mov,那麼應該怎麼辦?
通過中斷進入內核。
3.系統調用是如何實現的?
也就是說插座背後電路圖是怎麼連接的呢?
硬件提供了主動進入內核的方法
對於Intel x86 那就是int指令
*int指令將使CS中的CPL改為0,“進入內核”
*這是用戶程序發起的調用內核代碼的唯一方式
int 0x80
系統調用的核心:
(1) 用戶程序中包含一段包含int指令的代碼
(2) 操作系統寫中斷處理,獲取想調程序的編號
(3) 操作系統根據編號執行相應的代碼。
系統調用的實現
system_call()函數實現了系統調用處理程序。
然後根據EAX中所包含的系統調用號調用對應的服務例程:
call* sys_call_table(0,%eax,4)
sys_call_table+4*%eax就是相應系統調用處理函數的入口
4表示每個系統調用(函數)佔用4個字節。
在sys_call_table.c中
syscall_handler_t *sys_call_table[] = {
[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
[ __NR_exit ] (syscall_handler_t *) sys_exit,
[ __NR_fork ] (syscall_handler_t *) sys_fork,
[ __NR_read ] = (syscall_handler_t *) sys_read,
[ __NR_write ] = (syscall_handler_t *) sys_write,
...
}
sys_call_table是一個全局函數數組
sys_write對應的下標是4,所以__NR_write=4
__NR_write放在eax寄存器中
eax=4,函數的入口地址長度也是4
整個過程如下
閱讀更多 有理想的代碼dog 的文章