每一个系统调用号都对应有一个系统调用
接下来就是系统调用宏的展开
没有参数的系统调用的宏展开
!!!代码6::
带一个参数的系统调用的宏展开
!!!代码7::
两个参数
代码8::
#define _syscall2(type,name,type1,arg1,type2,arg2) \
三个参数的
代码9::
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
四个参数的
代码10::
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
五个参数的
代码11::
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5) \
六个参数的
代码12::
#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5,type6,arg6) \
_res); \
从这段代码我们可以看出int $0x80通过软中断开触发系统调用,当发生调用时,函数中的name会被系统系统调用名所代替。然后调用前面所讲的system_call。这个过程里包含了系统调用的初始化,系统调用的初始化原代码在:
arch/i386/kernel/traps.c中每当用户执行int 0x80时,系统进行中断处理,把控制权交给内核的system_call。
整个系统调用的过程可以总结如下:
1、执行用户程序(如:fork)
2、根据glibc中的函数实现,取得系统调用号并执行int $0x80产生中断。
3、进行地址空间的转换和堆栈的切换,执行SAVE_ALL。
4、进行中断处理,根据系统调用表调用内核函数。
5、执行内核函数。
6、执行RESTORE_ALL并返回用户模式
解了系统调用的实现及调用过程,我们可以根据自己的需要来对内核的系统调用作修改或添加。希望上文都大家能有所帮助。