1.什么是系統調用
系統調用,指的是操作系統提供給用戶程序調用的一組特殊接口,用戶程序可以根據這組接口獲得操作系統內核的服務。它規定了用戶進程陷入內核的具體位置,或者說規划了用戶訪問內核的路徑,只能從固定位置進入內核。
2.linux的系統調用
對於現代操作系統來說,系統調用是用戶空間和內核通訊的普遍手段,linux也不例外。按照功能區域,linux系統調用大致分為進程控制,文件訪問,系統控制,存儲管理,網絡管理,進程通訊等,詳細說明可以通過man 2 syscalls命令查看manpage說明。
系統調用,僅僅通過軟中斷機制向內核提交請求,進入系統調用對應服務。linux提供的用戶編程接口遵循了POSIX標准,這套標准除了定義一些標准的C函數外,提供了一套封裝例程將系統調用封裝供用戶編程使用。不過封裝並非必須的,如果你願意直接調用,linux內核也提供了一個syscall()函數來實現調用。通過下面一個例子了解C庫調用和直接調用的區別。
/*
** file: demo.c
** author: eric.xu
** date: 2016-02-25
*/
#include <syscall.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
int main(void)
{
long id1, id2;
/* system call no 20, __NR_getpid equal to SYS_getpid */
id1 = syscall(__NR_getpid);
printf("sys_call getpid %ld\n", id1);
/* libc getpid */
id2 = getpid();
printf("libc getpid %ld\n", id2);
return 0;
}
編譯運行,可以看到兩者結果一致。
sys_call getpid 2899
libc getpid 2899
3.linux系統調用實現
當用戶態的進程調用一個系統調用時,CPU切換到內核態並開始執行內核函數。因為內核中每個系統調用都有唯一的標號,所以用戶態調用必須傳遞一個系統調用號的參數來確定具體的系統調用函數。所有的系統調用函數都是整數,在內核中,整數和0表示系統調用成功結束,負數則表示出錯條件,而這個錯誤值會存放在errno變量中作為出錯碼返回給應用程序。
linux系統調用使用軟中斷實現,在x86架構中調用int $0x80匯編指令,這條指令會產生向量為128的異常。而在arm架構中通過SWI指令進入內核空間,下面看下這條指令的格式:
SWI {cond} immed24;其中immed24表示24位立即數
SWI異常中斷處理程序需要通過讀取引起軟件中斷的SWI指令,取得24位立即數。基本步驟是在SWI異常產生后,訪問SPSR寄存器判斷該指令是ARM指令還是Thumb指令,然后通過訪問LR寄存器得到整條指令地址,緊接着拿到該條指令,獲取最低24位立即數。
(未完待續)
