Arm Linux系统调用流程详细解析
系统调用是操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。
1、用户可以通过两种方式使用系统调用:
第一种方式是通过C库函数,包括系统调用在C库中的封装函数和其他普通函数。
第二种方式是使用_syscall宏。2.6.18版本之前的内核,在include/asm-i386/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)
其中,type表示所生成系统调用的返回值类型,name表示该系统调用的名称,typeN、argN分别表示第N个参数的类型和名称,它们的数目和_syscall后面的数字一样大。
这些宏的作用是创建名为name的函数,_syscall后面跟的数字指明了该函数的参数的个数。
比如sysinfo系统调用用于获取系统总体统计信息,使用_syscall宏定义为:
_syscall1(int, sysinfo, struct sysinfo *, info);
展开后的形式为:
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系统调用的实例。
代码清单5.1 sysinfo系统调用使用实例
#include#include #include #include /* for struct sysinfo */ _syscall1(int, sysinfo, struct sysinfo *, info); int main(void) { struct sysinfo s_info; int error; error = sysinfo(&s_info); printf("code error = %d/n", error); printf("Uptime = %lds/nLoad: 1 min %lu / 5 min %lu / 15 min %lu/n" "RAM: total %lu / free %lu / shared %lu/n" "Memory in buffers = %lu/nSwap: total %lu / free %lu/n" "Number of processes = %d/n", s_info.uptime, s_info.loads[0], s_info.loads[1], s_info.loads[2], s_info.totalram, s_info.freeram, s_info.sharedram, s_info.bufferram, s_info.totalswap, s_info.freeswap, s_info.procs); exit(EXIT_SUCCESS); }
但是自2.6.19版本开始,_syscall宏被废除,我们需要使用syscall函数,通过指定系统调用号和一组参数来调用系统调用。
syscall函数原型为:
int syscall(int number, ...);
其中number是系统调用号,number后面应顺序接上该系统调用的所有参数。下面是gettid系统调用的调用实例。
代码清单5.2 gettid系统调用使用实例
#include#include #include #define __NR_gettid 224 int main(int argc, char *argv[]) { pid_t tid; tid = syscall(__NR_gettid); }
大部分系统调用都包括了一个SYS_符号常量来指定自己到系统调用号的映射,因此上面第10行可重写为:
tid = syscall(SYS_gettid);
2 系统调用与应用编程接口(API)区别
应用编程接口(API)与系统调用的不同在于,前者只是一个函数定义,说明了如何获得一个给定的服务,而后者是通过软件中断向内核发出的一个明确的请求。POSIX标准针对API,而不针对系统调用。Unix系统给程序员提供了很多API库函数。libc的标准c库所定义的一些API引用了封装例程(wrapper
ArmLinux系统调 相关文章:
- ARM Linux下添加新的系统调用(11-21)
- 《ARM与Linux些许问题》第四章:ARM平台系统调用原理分析(11-09)
- Arm linux 系统调用分析(11-09)
- Android arm linux 系统调用实现(11-09)
- arm linux 系统调用实现(11-09)
- Arm Linux系统调用流程详细解析SWI(11-09)