5.1.5 如何使用系統調用linux
如圖5.2所示,用戶應用能夠經過兩種方式使用系統調用。第一種方式是經過C庫函數,包括系統調用在C庫中的封裝函數和其餘普通函數。函數
|
圖5.2 使用系統調用的兩種方式 |
第二種方式是使用_syscall宏。2.6.18版本以前的內核,在include/asm-i386/unistd.h文件中定義有7個_syscall宏,分別是:spa
- _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)
其中,type表示所生成系統調用的返回值類型,name表示該系統調用的名稱,typeN、argN分別表示第N個參數的類型和名稱,它們的數目和_syscall後面的數字同樣大。這些宏的做用是建立名爲name的函數,_syscall後面跟的數字指明瞭該函數的參數的個數。code
好比sysinfo系統調用用於獲取系統整體統計信息,使用_syscall宏定義爲:ci
- _syscall1(int, sysinfo, struct sysinfo *, info);
展開後的形式爲:get
- int sysinfo(struct sysinfo * info)
- {
- long __res;
- __asm__ volatile("int $0x80" : "=a" (__res) : "0" (116),"b" ((long)(info)));
- do {
- if ((unsigned long)(__res) >= (unsigned long)(-(128 + 1))) {
- errno = -(__res);
- __res = -1;
- }
- return (int) (__res);
- } while (0);
- }
能夠看出,_syscall1(int, sysinfo, struct sysinfo *, info)展開成一個名爲sysinfo的函數,原參數int就是函數的返回類型,原參數struct sysinfo *和info分別構成新函數的參數。原型
在程序文件裏使用_syscall宏定義須要的系統調用,就能夠在接下來的代碼中經過系統調用名稱直接調用該系統調用。下面是一個使用sysinfo系統調用的實例。it
代碼清單5.1 sysinfo系統調用使用實例io
- 00 #include <stdio.h>
- 01 #include <stdlib.h>
- 02 #include <errno.h>
- 03 #include <linux/unistd.h>
- 04 #include <linux/kernel.h> /* for struct sysinfo */
- 05
- 06 _syscall1(int, sysinfo, struct sysinfo *, info);
- 07
- 08 int main(void)
- 09 {
- 10 struct sysinfo s_info;
- 11 int error;
- 12
- 13 error = sysinfo(&s_info);
- 14 printf("code error = %d\n", error);
- 15 printf("Uptime = %lds\nLoad: 1 min %lu / 5 min %lu / 15 min %lu\n"
- 16 "RAM: total %lu / free %lu / shared %lu\n"
- 17 "Memory in buffers = %lu\nSwap: total %lu / free %lu\n"
- 18 "Number of processes = %d\n",
- 19 s_info.uptime, s_info.loads[0],
- 20 s_info.loads[1], s_info.loads[2],
- 21 s_info.totalram, s_info.freeram,
- 22 s_info.sharedram, s_info.bufferram,
- 23 s_info.totalswap, s_info.freeswap,
- 24 s_info.procs);
- 25 exit(EXIT_SUCCESS);
- 26 }
可是自2.6.19版本開始,_syscall宏被廢除,咱們須要使用syscall函數,經過指定系統調用號和一組參數來調用系統調用。asm
syscall函數原型爲:
- int syscall(int number, ...);
其中number是系統調用號,number後面應順序接上該系統調用的全部參數。下面是gettid系統調用的調用實例。
代碼清單5.2 gettid系統調用使用實例
- 00 #include <unistd.h>
- 01 #include <sys/syscall.h>
- 02 #include <sys/types.h>
- 03
- 04 #define __NR_gettid 224
- 05
- 06 int main(int argc, char *argv[])
- 07 {
- 08 pid_t tid;
- 09
- 10 tid = syscall(__NR_gettid);
- 11 }
大部分系統調用都包括了一個SYS_符號常量來指定本身到系統調用號的映射,所以上面第10行可重寫爲:
- tid = syscall(SYS_gettid);