Linux中應用程序如何使用系統調用syscall
最近在做Android,其中一個任務是寫一個能在Linux命令行運行的測試AP,運行這個AP就能關閉設備電源,即Power Off。
在 Linux內核中已經找到了關閉電源的函數kernel_power_off(),然后也知道了在sys_reboot()函數中調用 kernel_power_off()的,但是linux的應用程序怎么調用sys_reboot()呢? 經過1天的研究,終于搞明白了
這樣的函數屬于linux的系統調用函數(System call),需要用system call的方式調用,一共有下面3中途徑:
一、使用標準C庫函數
例如我們使用open(), read(), write()等標準C函數時,實際上是經過C庫包裝了的sys_open(),sys_read(),sys_write()等函數,這個包裝過程不用我們操心。這應該是屬于隱性調用system call。
二、在Linux 2.6.18以前版本
include/asm-arm/unistd.h文件中定義了7個_syscall宏,分別是:
_syscall0(type, name)
_syscall1(type, name,type1,arg1)
_syscall2(type, name,type1,arg1,type2,arg2)
_syscall3(type, name,type1,arg1,type2,arg2,type3,arg3)
_syscall4(type, name,type1,arg1,type2,arg2,type3, arg3,type4,arg4)
_syscall5(type, name,type1,arg1,type2,arg2,type3, arg3,type4,arg4,type5,arg5)
_syscall6(type, name,type1,arg1,type2,arg2,type3, arg3,type4,arg4,type5,arg5,type6,arg6)
這7個宏是用來產生系統調用的函數名的,其中type表示系統調用的返回值類型,name表示該系統調用的名稱,typeN、argN分別表示第N個參數的類型和名稱,它們的數目和_syscall后面的數字一樣大。
另外,include/linux/syscalls.h文件中定義有所用系統調用函數的原型,例如:
asmlinkage int sysinfo(struct sysinfo * info);
在需要系統調用的時候,先找到要調用的函數的聲明,看有多少個參數,然后用上面7個宏中的對應的一個,產生函數名,還是以sysinfo為例:
_syscall1(int, sysinfo, struct sysinfo *, info);
然后在調用的地方直接用sysinfo()函數就可以了:
struct sysinfo s_info;
int error;
error = sysinfo(&s_info);
三、在Linux 2.6.19之后的版本
上面的7個宏明顯有問題:不近麻煩,而且最多只有6個參數,在2.6.19以后的linux中,廢除了_syscallx這7和宏,而使用syscall()函數,這個函數定義在syscall.h中:
int syscall(int number, ...);
有一個新的概念:系統調用號,就是所用系統調用對應的編號,它們定義在include/asm-arm/unistd.h中。
當需要系統調用時,直接用這個函數,參數number就是需要的函數的系統調用號,例如上面的例子就變成:
struct sysinfo s_info;
syscall(__NR_sysinfo, &s_info);
上面的方法中描述的目錄可能每個平臺上都不太一樣,但大概都差不多,文件名應該是一樣的