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); 
相关文章
相关标签/搜索