本文所有的分析内容都是基于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. asp.net发邮件功能

    protected void SendMail() { try { string CreaterName = ""; string examiner = ""; ...

  2. 使用wait()与notify()实现线程间协作

    调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁.这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中.可以通过notify()/n ...

  3. 实现UniqueAttribute唯一性约束,sqlunique约束[转]

    using System; using System.ComponentModel.DataAnnotations; using System.Data.Entity; namespace Zwj.T ...

  4. float和double的精度

    作者: jillzhang 联系方式:jillzhang@126.com 原网址:http://blog.csdn.net/wuna66320/article/details/1691734 1 范围 ...

  5. php简写表达式,&& or || 缩写条件语句

    有时候学的多了, 好多小细节 都忘了 ,比如 简单的表达式, 三元表达式   ?:; $aa or $bb 表达式 等等! 写一些简单的表达式,备忘! php用&&和||缩写条件语句 ...

  6. hdoj 1385Minimum Transport Cost

    卧槽....最近刷的cf上有最短路,本来想拿这题复习一下.... 题意就是在输出最短路的情况下,经过每个节点会增加税收,另外要字典序输出,注意a到b和b到a的权值不同 然后就是处理字典序的问题,当松弛 ...

  7. 用HTML做的简单的个人简历

    <html> <head> <title>table表格</title> <style type="text/css"> ...

  8. code of C/C++(3) - 从 《Accelerated C++》源码学习句柄类

    0  C++中多态的概念 多态是指通过基类的指针或者引用,利用虚函数机制,在运行时确定对象的类型,并且确定程序的编程策略,这是OOP思想的核心之一.多态使得一个对象具有多个对象的属性.class Co ...

  9. Ubuntu日常问题搜集和解决办法

    搜集了日常工作中linuxmint的使用的命令备份和遇到的问题以及解决办法.(持续更新中) 保持ssh链接超时不自动断开 用ssh链接服务端,一段时间不操作或屏幕没输出(比如复制文件)的时候,会自动断 ...

  10. 《JavaScript高级程序设计》读书笔记--(1)JavaScript简介

    概述 JavaScript是一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HT ...