本文所有的分析内容都是基于Linux3.18.6内核,鉴于对应不同内核版本,系统调用的实现不相同。若需要分析其他版本内核的系统调用的实现过程,请谨慎参考。
system_call函数的功能是用来响应外壳函数发起的0x80中断,当外壳函数通过,其位于arch/x86/kernel/entry_32.S文件内。具体的执行流程,上一篇分析已列出,不再赘述。程序片段如下所示:
ENTRY(system_call)
RING0_INT_FRAME # can't unwind into user space anyway
ASM_CLAC
pushl_cfi %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation / emulation
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
syscall_after_call:
movl %eax,PT_EAX(%esp) # store the return value
syscall_exit:
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
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work restore_all:
TRACE_IRQS_IRET
restore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
movl 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), %ah
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << ) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << ) | USER_RPL), %eax
CFI_REMEMBER_STATE
je ldt_ss # returning to user-space with LDT SS
#endif
restore_nocheck:
RESTORE_REGS # skip orig_eax/error_code
irq_return:
INTERRUPT_RETURN
  • 其中RING0_INT_FRAME是一个宏,在/arch/x86/kernel/entry_32.S文件内。展开如下:
.macro RING0_INT_FRAME
CFI_STARTPROC simple
CFI_SIGNAL_FRAME
CFI_DEF_CFA esp, *
/*CFI_OFFSET cs, -*;*/
CFI_OFFSET eip, -*
.endm
  • ASM_CLAC同样是一个宏,定义在/arch/x86/include/asm/smap.h文件内。作用是加强SMAP保护的作用( Supervisor Mode Access Prevention 管理模式访问保护,intel提供了两条指令STAC和CLAC用于临时打开/关闭这个功能 )。
  • 接下来将eax压栈以保存系统调用号。
  • SAVE_ALL宏展开为:
.macro SAVE_ALL
cld
PUSH_GS
pushl_cfi %fs
/*CFI_REL_OFFSET fs, ;*/
pushl_cfi %es
/*CFI_REL_OFFSET es, ;*/
pushl_cfi %ds
/*CFI_REL_OFFSET ds, ;*/
pushl_cfi %eax
CFI_REL_OFFSET eax,
pushl_cfi %ebp
CFI_REL_OFFSET ebp,
pushl_cfi %edi
CFI_REL_OFFSET edi,
pushl_cfi %esi
CFI_REL_OFFSET esi,
pushl_cfi %edx
CFI_REL_OFFSET edx,
pushl_cfi %ecx
CFI_REL_OFFSET ecx,
pushl_cfi %ebx
CFI_REL_OFFSET ebx,
movl $(__USER_DS), %edx
movl %edx, %ds
movl %edx, %es
movl $(__KERNEL_PERCPU), %edx
movl %edx, %fs
SET_KERNEL_GS %edx
.endm
  • 首先是将寄存器内容压栈,保存当前上下文。接着将_USER_DS内容写入DS(数据段寄存器)和ES(代码段寄存器)两个寄存器。目的是为了减少从内核态返回的开销【1】。
  • 获取thread_info结构的地址,检测thread_info中的标志是否有跟踪。
  • 有跟踪则执行系统跟踪的代码,然后通过将给定的系统调用号与NR_syscalls作比较以检查其有效性。
  • syscall_call是整个代码的关键部分,通过传进来的系统调用号,在系统调用表sys_call_table中取对应的系统调用处理函数,表项以32位存放,所以给调用号乘以4。
  • 调用结束之后,储存处理函数的返回值eax
  • 在返回用户态之前先关中断。
  • syscall_exit_work进行了进程调度、消息传递的工作,进程切换可导致新的中断或系统调用
  • 【work_pending中判断NEED_RESCHED,由结果执行work_resched重新进行进程调度,或进入work_notifysig处理信号】
  • 最后从restore开始执行退出调用的操作。
 
ps:安利一下用的在线流程图绘制网站https://www.processon.com/tour,方便、功能足够。
参考文献

By:昆仑雪狐

原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

system_call中断处理过程分析的更多相关文章

  1. 分析system_call中断处理过程

    分析system_call中断处理过程 上周我们使用gcc内嵌汇编调用系统调用,这次我们具体分析下过程. 将getpid嵌入menuos 代码从github下载,步骤如下: 1. 增加一个函数,get ...

  2. 20135202闫佳歆--week5 分析system_call中断处理过程--实验及总结

    week 5 实验:分析system_call中断处理过程 一.使用gdb跟踪分析一个系统调用内核函数(上周选择那一个系统调用)--getpid 复习视频: 如何实现? - 更新menu代码到最新版 ...

  3. 《Linux内核分析》-- 扒开系统调用的三层皮(下)之system_call中断处理过程 20135311傅冬菁

    20135311傅冬菁  原创作品 <Linux内核分析>MOOC课程 分析system_call中断处理过程 内容分析与总结: 系统调用在内核代码中的工作机制和初始化 系统调用在用户态中 ...

  4. 作业五:分析system_call中断处理过程

    分析system_call中断处理过程 一.MesuSO增加getpid和getpid-asm 二.使用GDB跟踪系统调用内核函数sys_getpid 分析system_call中断处理过程 使用gd ...

  5. 《Linux内核分析》第五周:分析system_call中断处理过程

    实验 分析system_call中断处理过程 使用gdb跟踪分析一个系统调用内核函数(您上周选择那一个系统调用),系统调用列表参见http://codelab.shiyanlou.com/xref/l ...

  6. Linux内核分析-分析system_call中断处理过程

    姓名:江军 ID:fuchen1994 分析system_call中断处理过程 使用gdb跟踪分析一个系统调用内核函数(您上周选择那一个系统调用),系统调用列表参见http://codelab.shi ...

  7. Linux内核设计第五周学习总结 分析system_call中断处理过程

    陈巧然原创作品 转载请注明出处   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 使用gdb跟踪分析一 ...

  8. Linux内核分析第五周学习总结——分析system_call中断处理过程

    Linux内核分析第五周学习总结--分析system_call中断处理过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  9. 通过分析system_call中断处理过程来深入理解系统调用

    通过分析system_call中断处理过程来深入理解系统调用 前言说明 本篇为网易云课堂Linux内核分析课程的第五周作业,上一次作业中我以2个系统调用(getpid, open)作为分析实例来分析系 ...

随机推荐

  1. c#连接vertica数据库

    项目前期使用mysql数据库,大约每天200w数据量,十天1500w数据量之后,读取写入都会很慢,而且经常锁表,后来采用vertica数据库,下面分享vertica数据库使用方法,以及大批量数据快速写 ...

  2. sql脚本多服务器操作

    --创建链接服务器exec sp_addlinkedserver 'srv_lnk','','SQLOLEDB','IP' exec sp_addlinkedsrvlogin 'srv_lnk','f ...

  3. javascript数组的方法总结,非常实用的!

    在ES5中,一共有9个Array方法 http://kangax.github.io/compat-table/es5/ 注* 九个方法 Array.prototype.indexOfArray.pr ...

  4. cacti监控juniper路由器

    之前也没有写过博客,但是最近一直在做监控.从网上查找很多资料都还是感觉差一点.所以自己添加一份我在cacti监控路由器的步骤. 环境,ubuntu14.04,apt-get install cacti ...

  5. Dom4j解析xml

    public class Dom4jTest { // Dom4j解析xml // 因为所有的方法都需要Dom树 static Document document = null; static Ele ...

  6. Jquery的各种验证

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  7. μC/OS-Ⅲ系统中的任务就续表

    μC/OS-Ⅲ支持任意数目的不同优先级.一般情况下64级优先级就足够了. 在μC/OS-Ⅲ中所有已经就绪等待运 行的任务都被放入一个我为的“就续表”(ready list)中.就续表包括两部分:一个就 ...

  8. C++学习进度0

    昨天,又把<C++ primer> 刷了一遍,这一次看的是陈硕大大的评注版,重点看了陈硕的注释,<Accelerated C++>去年就把代码巧了一遍,<C++ prim ...

  9. Listener实现单态登陆

    MyEclipse中新建Web Project项目,完整目录如下: 需要的jar包为commons-logging-xxx.jar 1.singleton.jsp <%@ page langua ...

  10. 【转】2014年25款最好的jQuery插件

    2014年25款最好的jQuery插件 来源:Specs' Blog-就爱PHP   时间:2014-12-30 10:24:10   阅读数:2267 分享到: 0 http://www.php10 ...