第五课-系统调用跟踪
来源:互联网 发布:淘宝怎么搜福利 编辑:程序博客网 时间:2024/05/18 00:00
赵连讯 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
本节课的实验内容主要是跟踪系统调用过程,理解系统调用的整个过程。重点分析系统调用的保存与返回流程。
我从menu开始做起。
- 修改menu,添加时间系统调用
修改test.c源代码,增加系统调用函数time的函数如下:int ShowTime(void){time_t tt;struct tm * t;//get time nowtt = time(NULL);t = localtime(&tt);//show timeprintf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);return 0;}int ShowTimeAsm(void){time_t tt;struct tm * t;//get time now//tt = time(NULL);asm volatile("mov $0,%%ebx\n\t""mov $0xd,%%eax\n\t""int $0x80\n\t""mov %%eax,%0\n\t":"=m"(tt));t = localtime(&tt);//show timeprintf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);return 0;}int main(){ PrintMenuOS(); SetPrompt("MenuOS>>"); MenuConfig("version","XXX V1.0(Menu program v1.0 inside)",NULL);MenuConfig("time","show time",ShowTime);MenuConfig("time-asm","show time from asm",ShowTimeAsm); MenuConfig("quit","Quit from XXX",Quit); ExecuteMenu();}说明:注意头文件time.h的调用。
在muconfig中使用time就能打印输出当前的时间;输入time-asm就能打印输出当前的时间。
在menu菜单下重新编译,编译指令如下:
gcc -o init linktable.c menu.c test.c -m32 -static -lpthread
因为要生成init可执行程序才能在系统最后被调用,因为当前文件系统中没有其他库的支持,因此程序依赖的动态库必须使用静态库来编译到内核中。
- 2.制作根文件系统
拷贝menu中生成的init可执行程序到rootfs中到rootfs文件目录下执行如下语句:
find . | cpio -o -Hnewc | gzip -9 > ../rootfs.img
将会生成新的rootfs.img镜像文件
- 3.跟踪内核
执行如下语句:打开一个命令行终端,输入如下语句,执行内核
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
内核执行会弹出新的显示终端。
重新打开一个新的命令行终端:
在此,调试内核
输入gdb
在gdb下进入Linuxkernel的当前目录下
file linux3.18.6/vmlinux
target remote:1234
b start_kernel
b sys_time 在time的系统调用处设置断点,在后面就没有机会设置了,因为无法让内核重新停止了。
c
此时内核运行到start_kernel,也就是内核的入口语句处。
list
可查看当前语句
c
内核继续运行将会进入menu语句中。
输入time后回车
可在gdb中看到sys_time的系统调用停止语句。
内核执行的图片显示:
问题:
在实际操作的过程中,总是会出现运行了time之后,系统停止的时候,就不能再响应鼠标了。结果导致我不得不停止试验,再来一次。代码必须重新写一次。非常慢。
停止的位置如下:
分析代码
虽然此时再也无法响应鼠标了,但是仍然可以人为的分析代码。
代码进入了kernel/time/time.c中第63行,代码如下:
SYSCALL_DEFINE1(time, time_t __user *, tloc){time_t i = get_seconds();if (tloc) {if (put_user(i,tloc))return -EFAULT;}force_successful_syscall_return();return i;}
系统调用,获得秒的时间值。根据老师课程讲解,函数返回将不会看到。
- 分析sys_call这个调用
ENTRY(system_call)//只要系统执行了int 0x80的时候,此处就会执行
RING0_INT_FRAME# can't unwind into user space anywayASM_CLACpushl_cfi %eax# save orig_eaxSAVE_ALL://保护现场GET_THREAD_INFO(%ebp)# system call tracing in operation / emulationtestl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)jnz syscall_trace_entrycmpl $(NR_syscalls), %eaxjae syscall_badsyssyscall_call:call *sys_call_table(,%eax,4)//系统调用表,eax就是系统调用号,会指向timesyscall_after_call:movl %eax,PT_EAX(%esp)# store the return value保存返回值syscall_exit:LOCKDEP_SYS_EXITDISABLE_INTERRUPTS(CLBR_ANY)# make sure we don't miss an interrupt 禁止中断时为了不要丢掉中断# setting need_resched or sigpending# between sampling and the iretTRACE_IRQS_OFFmovl TI_flags(%ebp), %ecxtestl $_TIF_ALLWORK_MASK, %ecx# current->workjne syscall_exit_work //会跳转到退出工作处restore_all:TRACE_IRQS_IRETrestore_all_notrace:
<pre name="code" class="objc">#ifdef CONFIG_X86_ESPFIX32movl PT_EFLAGS(%esp), %eax# mix EFLAGS, SS and CS# Warning: PT_OLDSS(%esp) contains the wrong/random values if we# are returning to the kernel.# See comments in process.c:copy_thread() for details.movb PT_OLDSS(%esp), %ahmovb PT_CS(%esp), %alandl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eaxcmpl $((SEGMENT_LDT << 8) | USER_RPL), %eaxCFI_REMEMBER_STATEje ldt_ss# returning to user-space with LDT SS#endifrestore_nocheck:RESTORE_REGS 4# skip orig_eax/error_codeirq_return:INTERRUPT_RETURN
testl $_TIF_WORK_SYSCALL_EXIT, %ecx
jz work_pending #跳转到work pending 处其实是处理信号和重新调度
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_ANY)# could let syscall_trace_leave() call#使能中断和前文中禁止中断是相呼应的
# schedule() instead
movl %esp, %eax
call syscall_trace_leave
jmp resume_userspace//恢复到用户空间去
END(syscall_exit_work)
testb $_TIF_NEED_RESCHED, %cl #观察是否需要进一步的重新schedule,产生进程调度
jz work_notifysig#如果没有进程调度则进行信号处理
work_resched:#/发生进程调度的时候,调用schedule函数
call schedule
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY)# make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
andl $_TIF_WORK_MASK, %ecx# is there any work to be done other
# than syscall tracing?
jz restore_all
testb $_TIF_NEED_RESCHED, %cl
jnz work_resched #可能产生返回的进程调度过程
work_notifysig: # deal with pending signals and
# notify-resume requests开始处理正在pending的信号
#ifdef CONFIG_VM86
testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
movl %esp, %eax
jne work_notifysig_v86# returning to kernel-space or
# vm86-space
1:
#else
movl %esp, %eax
#endif
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
movb PT_CS(%esp), %bl
andb $SEGMENT_RPL_MASK, %bl
cmpb $USER_RPL, %bl
jb resume_kernel
xorl %edx, %edx
call do_notify_resume
jmp resume_userspace
#ifdef CONFIG_VM86
ALIGN
work_notifysig_v86:
pushl_cfi %ecx# save ti_flags for do_notify_resume
call save_v86_state# %eax contains pt_regs pointer
popl_cfi %ecx
movl %eax, %esp
jmp 1b
#endif
END(work_pending)
总结:
对信号处理和发生进程调度部分分析的还不够透彻,需要好好的分析。
- 第五课-系统调用跟踪
- strace跟踪系统调用
- 第五章 系统调用
- Linux 系统调用的跟踪
- linux 系统调用跟踪---strace
- 使用strace跟踪系统调用
- 用strace跟踪系统调用
- Linux strace 系统调用跟踪
- 应用的系统调用跟踪
- strace工具跟踪系统调用和信号
- Syscall系统调用Linux内核跟踪
- Syscall系统调用Linux内核跟踪
- Syscall系统调用Linux内核跟踪
- 调试_应用的系统调用跟踪
- linux strace命令--跟踪系统调用
- 跟踪sys_mkdir的系统调用过程
- 系统调用跟踪命令strace和dtruss
- strace命令跟踪程序系统调用
- 用c++编写计时器的步骤及其函数代码
- hdu--Let's go to play
- java并发编程——ConcurrentHashMap
- 老罗专访:Android 源码之旅
- java小程序之从方法中返回数组
- 第五课-系统调用跟踪
- Mybatis第五弹
- C++ 宏定义
- Arch的VBox安装笔记
- 15电气 齐振昊 实验名称:在VB中三个数的排序
- Makefile初学(2)
- Codeforces 622F (拉格朗日插值 费马小定理)
- mysql5.7安装Table 'mysql.user' doesn't exist
- spring+springMVC,声明式事务失效,原因以及解决办法