系统调用,其实简单的说就是用户态和内核态交互的一种方式。不过是单向,只能用户态向内核态交互而已。
大家熟知的系统调用有open read write等。那么系统调用是怎么实现用户态陷入到内核态的呢?相信大家和我一样很好奇,那么就开始我们的探索之旅吧。
现在Linux2.6.18内核版本后,都改为了使用SYSCALL_DEFINEx来定义系统调用。但是本质上还是sys_xxx的模式。所以我们还是以2.6.18以前版本的内核为基础,从最基本的系统调用知识来展开叙述。SYSCALL_DEFINEx的相关内容会在以后的文章中为大家叙述。
我们在X86架构下来进行举例。系统调用在用户态,最终都会调用到同样的一组接口。即_syscall0~_syscall6。那么这一组接口是干什么的呢,我们来看一下它的定义(在unistd.h中):
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \ : "=a" (__res) \
: "0" (__NR_##name)); \
__syscall_return(type,__res); \
}
#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1))); \
__syscall_return(type,__res); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c&#