1. 说明
系统调用(System Call)是操作系统为在用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互提供的一组接口。当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系统调用函数。
2. 内嵌汇编
下面以获取系统当前时间为例,探讨系统调用方式。
1. glibc调用
int tt = time(NULL);
2. syscall调用
linux-2.6.32/arch/x86/kernel/syscall_table_32.S linux-2.6.32系统调用表
linux-3.18.6/arch/x86/kernel/syscall_table_32.S linux-2.6.32系统调用表
linux-3.5/arch/x86/syscalls/syscall_32.tbl linux-3.5系统调用表
通过查看 syscall_table_32.S 中断调用表文件得到sys_time中断调用号为13.
int tt = syscall(13);
3. 内嵌汇编
int tt = 0; asm("mov $0,%%ebx\n\t" "mov $13,%%eax\n\t" "int $0x80\n\t" "mov %%eax,%0\n\t" :"=m"(tt) ); printf( "time:%d\n", tt );
eax=13 传入系统调用号
ebx=0传入系统函数,相当于time(NULL)。如果有多个传入参数,可使用ebx,
ecx,edx,esi,edi,ebp 寄存器
eax 接收函数返回值,传出至tt
int $0x80 中断陷入,windows下采用0x2E作为系统调用入口
3. 扩展系统调用
glibc 中time()调用过程:用户态调用 time(),中断陷入内核态,调用内核函数 sys_time()。
可通过下列四步实现自定义系统调用:
linux-2.6.32/kernel/sys.c
sys_xxx(),实现系统调用
linux-2.6.32/arch/x86/include/asm/unistd.h
_NR_xxx,添加中断号宏定义
linux-2.6.32/arch/x86/kernel/syscall_table_32.S
.long sys_xx,添加中断汇编定义
linux-2.6.32/include/linux/syscalls.h
asmlinkage,导出该函数
参考资料:
《程序员的自我修养》