本章主要讲解在内核态跟踪调试一个系统调用,进一步分析系统调用的内核处理过程。
重现克隆新版本的meun,其中已添加了time/time-asm两个系统调用函数,time为C语言方式显示系统时间,time-asm为使用汇编方式显示系统时间。如图:
使用下列命令调试内核
‘cd .. #返回到LinuxKernel目录下‘
‘qemu -Kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s‘
启动gdb,将linux-3.18.6内核加载进来,连接到target remote 1234端口:
‘file linux-3.18.6/vmlinux‘
‘target remote:1234‘
设置断点,在sys_call处设置断点。当系统执行中断指令:int 0x80时,CPU会自动跳转到system_call函数。那具体来了解system_call是如何跳转与执行的呢?一下为system_call函数源码,下面来分析具体system_call与中断指令int 0x80的跳转关系。
ENTRY(system_call)
491 RING0_INT_FRAME # can‘t unwind into user space anyway
492 ASM_CLAC
493 pushl_cfi %eax # save orig_eax
494 SAVE_ALL
495 GET_THREAD_INFO(%ebp)
496 # system call tracing in operation / emulation
497 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
498 jnz syscall_trace_entry
499 cmpl $(NR_syscalls), %eax
500 jae syscall_badsys
501syscall_call:
502 call *sys_call_table(,%eax,4)
503syscall_after_call:
504 movl %eax,PT_EAX(%esp) # store the return value
505syscall_exit:
506 LOCKDEP_SYS_EXIT
507 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don‘t miss an interrupt
508 # setting need_resched or sigpending
509 # between sampling and the iret
510 TRACE_IRQS_OFF
511 movl TI_flags(%ebp), %ecx
512 testl $_TIF_ALLWORK_MASK, %ecx # current->work
513 jne syscall_exit_work
514
515restore_all:
516 TRACE_IRQS_IRET
517restore_all_notrace:
518#ifdef CONFIG_X86_ESPFIX32
519 movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
520 # Warning: PT_OLDSS(%esp) contains the wrong/random values if we
521 # are returning to the kernel.
522 # See comments in process.c:copy_thread() for details.
523 movb PT_OLDSS(%esp), %ah
524 movb PT_CS(%esp), %al
525 andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
526 cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
527 CFI_REMEMBER_STATE
528 je ldt_ss # returning to user-space with LDT SS
529#endif
530restore_nocheck:
531 RESTORE_REGS 4 # skip orig_eax/error_code
532irq_return:
533 INTERRUPT_RETURN
本节将仔细分析system_call作为一个中断服务程序的来龙去脉。
以time为例,在用户态调用time,通过gdb跟踪内核里面的系统调用函数sys_time,触发一个系统调用到执行这个系统调用的内核处理函数,再到最后系统调用返回到用户态。如图所示:
2018-2019-1 20189229《Linux内核原理与分析》第六周作业
原文:https://www.cnblogs.com/zisong/p/9980361.html