一、命运枷锁
每一个系统调用都有他们无法摆脱的命运—开始(entry)和结束(iret),无论在中间的过程是如何。他们的“始”与“终”都别无二致。
二、实验与分析
实验目的:使用gdb跟踪分析一个系统调用内核函数 (系统调用号39,创建文件夹)
实验步骤:
在test.c中加入如下代码
int MkDir(){
int flag=mkdir("/home/shiyanlou/Code/mydir");
printf("%d\n",flag);
if(flag == 0){
printf("success\n");
}else{
printf("failed\n");
}
return 0;
}
使用嵌入式汇编
int MkDir_asm(){
char *path ="/home/shiyanlou/Code/mydir_asm";
int flag = -1;
asm volatile(
"mov %1,%%ebx\n\t"
"mov $39,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
:"=m"(flag)
:"d" (path)
);
printf("%d\n",flag);
if(flag == 0){
printf("success\n");
}else{
printf("failed\n");
}
return 0;
}
以及以下两行代码
MenuConfig("newDir","create a new Dir",MkDir);
MenuConfig("newDir_asm","create a new Dir by asm",MkDir_asm);
make rootfs
使用gdb调试运行
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s –S
(gdb)file linux-3.18.6/vmlinux #加载符号表
(gdb)target remote:1234 #建立gdb和gdbserver之间的连接
(gdb)b sys_mkdir #在sys_mkdir建立断点
(gdb)c
之后无法使用gdb跟踪代码
三、总结
ENTRY(system_call) #系统调用入口(用户态->内核态)
RING0_INT_FRAME
ASM_CLAC
pushl_cfi %eax
SAVE_ALL #保存现场
GET_THREAD_INFO(%ebp)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(NR_syscalls), %eax
jae syscall_badsys
syscall_call: #发生系统调用
call *sys_call_table(,%eax,4) #查询相应的系统调用号
syscall_after_call:
movl %eax,PT_EAX(%esp) # 保存返回值
syscall_exit:
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY)
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testl $_TIF_ALLWORK_MASK, %ecx
jne syscall_exit_work
restore_all: #恢复现场
TRACE_IRQS_IRET
restore_all_notrace:
restore_nocheck:
RESTORE_REGS 4
irq_return: #返回
INTERRUPT_RETURN