Linux内核分析——扒开系统调用的三层皮(下)
来源:互联网 发布:保险网络增员话术 编辑:程序博客网 时间:2024/04/30 21:53
张瑜《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、实验内容
1. 通过内核的方式使用系统调用
上周是从用户态来看系统调用,这周是从内核方面来看这个问题
用到的命令:
rm menu -rf //强制删除当前menugit clone http://git.shiyanlou.com/mengning/menu.git //重新克隆新版本的menucd menulsmake rootfs //rootfs是事先写好的一个脚本,自动编译自动生成根文件系统,同时自动启动MenuOS
2. 将上周选择的系统调用添加到MenuOS中
在menu文件夹中的 test.c文件中,添加上周写的Gitpid和Gitpidasm代码
int Getpid(int argc , char * argv[]){int pid;pid=getpid();printf("pid=%d\n",pid);return 0;}int Getpidasm(int argc , char *argv[]){int pid;asm volatile("mov $0,%%ebx\n\t""mov $0x14,%%eax\n\t""int $0x80\n\t""mov %%eax, %0\n\t":"=m"(pid));printf("pid = %d\n",pid);return 0;}//在main函数中添加MenuConfig(“getpid","Show pid",Getpid);MenuConfig("getpid-asm","Show pid(asm)",Getpidasm);
重新make
3.使用gdb跟踪分析这该系统调用内核函数
用到的命令:
qemu -kernel linux.3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 调试。file linux-3.18.6/vmlinux 加载调试内核符号表。b 设置断点 n 单步执行
二、系统调用过程分析
1. 系统调用在内核代码中的工作机制和初始化
int 0x80——>system call:通过中断向量匹配
system call——>sys_xyz():通过系统调用号匹配
一旦执行int 0x80后立刻跳转到system_call执行
2. 系统调用system_call的处理过程
syscall_call 函数到系统调用服务例程通过系统调用号联系起来:
在上面执行软中断 0x80 时,系统调用号会被放入eax寄存器(参数的传递);
函数读取eax寄存器获取参数(当前系统调用的调用号),将其乘以4生成偏移地址。
其中 sys_call_table 基址在文件arch/x86/kernel/syscall_table_32.S 中定义,同时表中每一项例程的地址占用4个字节,所以上面乘以4。
由于系统调用例程在定义时时用 asmlinkage 标记了的,所以编译器仅从堆栈中获取该函数的参数。在进入system_call函数前,用户应用会把参数存放到寄存器中,system_call 函数执行时会首先把这些寄存器压入堆栈。这样对系统调用服务例程可以直接从堆栈照片能够获取参数。
3.从system_call开始到iret结束之间的过程
从整体过程来看,系统通过 int 0x80 从用户态进入内核态。在这个过程中系统先保存了中断环境,然后执行系统调用函数。system_call() 函数通过系统调用号查找系统调用表 sys_cal_table 来查找到具体的系统调用服务进程。在执行完系统调用后在执行 iret 之前,内核做了一系列检查,用于检查是否有新的中断产生。如果没有新的中断,则通过已保存的系统中断环境返回用户态。这样就完成了一个系统调用过程。系统调用通过 INT 0x80 进入内核,跳转到system_call() 函数,然后执行相应服务进程。因为代表了用户进程,所以这个过程并不属于中断上下文,而是属于进程上下文。
4.系统调用处理过程的汇编代码分析
无论是中断返回(ret_from_intr) ,还是系统调用返回,都使用了 work_pending 和resume_userspace。对于宏SAVE_ALL来说,这条语句会把将寄存器的值压入堆栈当中,压入堆栈的顺序对应struct pt_regs ,出栈时,这些值传递到struct pt_regs的成员,实现从汇编代码向C程序传递参数。struct pt_regs可以在arch/x86/include/asm/ptrace.h中查看。用户态到内核态需要int 0x80进行中断,只有生成了中断向量后才可以切换状态。中断处理让CPU停止当前工作转为执行系统内核中预设的一些任务,因此必须要对当前CPU执行的任务进行执行现场的保护工作,并对一些其他工作进行检查,完成调用后,再进行检查,才能执行iret返回。系统内部调用涉及CPU架构等内容,不同的CPU对于系统调用的汇编具体代码是不一样的。
.macro INTERRUPT_RETURN ; 中断返回 iret.endm.macro SAVE_ALL ; 保护现场 ....macro RESTORE_INT_REGS ....endmENTRY(system_call) SAVE_ALLsyscall_call: call *sys_call_table(,%eax,4) movl %eax, PT_EAX(%esp) ; store the return valuesyscall exit: testl $_TIF_ALLWORK_MASK, %ecx # current->work jne syscall_exit_workrestore_all: RESTORE_INT_REGSirq_return: INTERRUPT_RETURN ENDPROC(system_call)syscall_exit_work: testl $_TIF_WORK_SYSCALL_EXIT, %ecx jz work_pendingEND(syscall_exit_work)work_pending: testb $_TIF_NEED_RESCHED, %cl jz work_notifysigwork_resched: call schedule jz restore_allwork_notifysig: ... ; deal with pending signalsEND(work_pending)
- Linux内核分析——扒开系统调用的三层皮(下)
- 《Linux内核分析》(四)——扒开系统调用的三层皮(上)
- Linux内核分析——扒开系统调用的三层皮(上)
- Linux内核分析05-扒开系统调用的三层皮(下)
- Linux内核作业之扒开系统调用的三层皮(下)
- Linux内核分析4:扒开系统调用三层皮
- Linux系统调用-扒开系统调用的三层皮(下)
- 扒开系统调用三层皮(二)
- 第四讲、扒开系统调用的三层皮(上)
- 扒开系统调用的三层皮(上)
- 扒开系统调用的三层皮(一)
- System Call 扒开系统调用的三层皮[未完待续~]
- Linux内核分析——系统调用(下)
- Linux内核分析——系统调用(上)
- Linux内核分析之五——分析系统调用(system_call)的执行机制
- 《Linux内核分析》(五)——Linux系统调用的执行过程
- Linux系统调用的“三层皮”:API,中断服务程序,内核服务程序
- Linux内核分析实验4——系统调用
- 如何关掉Java里面的window边框
- keras中merge用法
- keras中Convolution1D的使用
- python中使用文件的读取编码问题和简单正则使用(一)
- python中使用文件的读取编码问题和简单正则使用(二)
- Linux内核分析——扒开系统调用的三层皮(下)
- ASP.net连接mysql数据库(使用MySql.Data.dll)
- 顺序表应用2:多余元素删除之建表算法
- 使用phantomjs新的
- 53. Maximum Subarray(unsolved)
- 群论&polya定理笔记
- 内存泄漏和内存溢出
- 安徽大学第九届大学生程序设计竞赛 网络预选赛 B
- H5 Manifest实现缓存刷新