5.1.5 如何使用系統調用

5.1.5  如何使用系統調用linux

如圖5.2所示,用戶應用能夠經過兩種方式使用系統調用。第一種方式是經過C庫函數,包括系統調用在C庫中的封裝函數和其餘普通函數。函數

 
圖5.2  使用系統調用的兩種方式

第二種方式是使用_syscall宏。2.6.18版本以前的內核,在include/asm-i386/unistd.h文件中定義有7個_syscall宏,分別是:spa

 
  1. _syscall0(type,name)  
  2. _syscall1(type,name,type1,arg1)  
  3. _syscall2(type,name,type1,arg1,type2,arg2)  
  4. _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)  
  5. _syscall4(type,name,type1,arg1,type2,arg2,type3,
    arg3,type4,arg4)  
  6. _syscall5(type,name,type1,arg1,type2,arg2,type3,
    arg3,type4,arg4,type5,arg5)  
  7. _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

 
  1. _syscall1(int, sysinfo, struct sysinfo *, info); 

展開後的形式爲:get

 
  1. int sysinfo(struct sysinfo * info)  
  2. {  
  3.     long __res;  
  4.     __asm__ volatile("int $0x80" : "=a" (__res) : "0" (116),"b" ((long)(info)));  
  5.     do {  
  6.         if ((unsigned long)(__res) >= (unsigned long)(-(128 + 1))) {  
  7.             errno = -(__res);  
  8.             __res  = -1;  
  9.         }  
  10.         return (int) (__res);  
  11.     } while (0);  

能夠看出,_syscall1(int, sysinfo, struct sysinfo *, info)展開成一個名爲sysinfo的函數,原參數int就是函數的返回類型,原參數struct sysinfo *和info分別構成新函數的參數。原型

在程序文件裏使用_syscall宏定義須要的系統調用,就能夠在接下來的代碼中經過系統調用名稱直接調用該系統調用。下面是一個使用sysinfo系統調用的實例。it

代碼清單5.1  sysinfo系統調用使用實例io

 
  1. 00 #include <stdio.h> 
  2. 01 #include <stdlib.h> 
  3. 02 #include <errno.h> 
  4. 03 #include <linux/unistd.h>         
  5. 04 #include <linux/kernel.h>       /* for struct sysinfo */  
  6. 05   
  7. 06 _syscall1(int, sysinfo, struct sysinfo *, info);  
  8.      07   
  9. 08 int main(void)  
  10. 09 {  
  11. 10     struct sysinfo s_info;  
  12. 11     int error;  
  13. 12   
  14. 13     error = sysinfo(&s_info);  
  15. 14     printf("code error = %d\n", error);  
  16. 15     printf("Uptime = %lds\nLoad: 1 min %lu / 5 min %lu / 15 min %lu\n"  
  17. 16         "RAM: total %lu / free %lu / shared %lu\n"  
  18. 17         "Memory in buffers = %lu\nSwap: total %lu / free %lu\n"  
  19. 18         "Number of processes = %d\n",  
  20. 19         s_info.uptime, s_info.loads[0],  
  21. 20         s_info.loads[1], s_info.loads[2],  
  22. 21         s_info.totalram, s_info.freeram,  
  23. 22         s_info.sharedram, s_info.bufferram,  
  24. 23         s_info.totalswap, s_info.freeswap,  
  25. 24         s_info.procs);  
  26. 25         exit(EXIT_SUCCESS);  
  27.      26 } 

可是自2.6.19版本開始,_syscall宏被廢除,咱們須要使用syscall函數,經過指定系統調用號和一組參數來調用系統調用。asm

syscall函數原型爲:

 
  1. int syscall(int number, ...); 

其中number是系統調用號,number後面應順序接上該系統調用的全部參數。下面是gettid系統調用的調用實例。

代碼清單5.2  gettid系統調用使用實例

 
  1. 00 #include <unistd.h> 
  2. 01 #include <sys/syscall.h> 
  3. 02 #include <sys/types.h> 
  4. 03   
  5. 04 #define __NR_gettid      224  
  6. 05   
  7. 06 int main(int argc, char *argv[])  
  8. 07 {  
  9. 08     pid_t tid;  
  10. 09   
  11. 10     tid = syscall(__NR_gettid);  
  12. 11 } 

大部分系統調用都包括了一個SYS_符號常量來指定本身到系統調用號的映射,所以上面第10行可重寫爲: 

 
  1. tid = syscall(SYS_gettid); 
相關文章
相關標籤/搜索