一、实验内容

1. 通过内核的方式使用系统调用

需要使用的命令

rm menu -rf //强制删除当前menu
git clone http://github.com/mengning/menu.git //重新克隆新版本的menu
cd menu
ls
make 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 ;
} 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 ;
}

  在main函数中添加

MenuConfig(“getpid","Show pid",Getpid);
MenuConfig("getpid-asm","Show pid(asm)",Getpidasm);

  重新make 后。可以看到menuOS有了getpid的命令,功能为返回当前进程的标识。

3.使用gdb跟踪分析这该系统调用内核函数

  系统中已经成功添加了该函数调用功能。然后对该程序进行调试分析,使用gdb跟踪分析这该系统调用内核函数。

  需要使用命令为

qemu -kernel  linux.3.18./arch/x86/boot/bzImage -initrd rootfs.img -s -S 调试。

file linux-3.18./vmlinux 加载调试内核符号表。

b 设置断点   n 单步执行  

二、系统调用过程分析 

1. 系统调用在内核代码中的工作机制和初始化

int 0x80——>system call:通过中断向量匹配

system call——>sys_xyz():通过系统调用号匹配

一旦执行int 0x80后立刻跳转到system_call执行

2. 系统调用system_call的处理过程

  syscall_call 函数到系统调用服务例程通过系统调用号联系起来:在上面执行软中断 0x80 时,系统调用号会被放入eax寄存器(参数的传递),system_call 函数读取eax寄存器获取参数(当前系统调用的调用号),将其乘以4生成偏移地址。然后以中断向量表(sys_call_table)为基址,以系统调用号所确定的为偏移地址相加得到最后的物理地址:基址+偏移地址 => 系统调用服务例程的地址。其中 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.系统调用处理过程的汇编代码分析

.macro INTERRUPT_RETURN  ; 中断返回
iret
.endm
.macro SAVE_ALL ; 保护现场
...
.macro RESTORE_INT_REGS
...
.endm ENTRY(system_call)
SAVE_ALL
syscall_call:
call *sys_call_table(,%eax,)
movl %eax, PT_EAX(%esp) ; store the return value
syscall exit:
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work
restore_all:
RESTORE_INT_REGS
irq_return:
INTERRUPT_RETURN
ENDPROC(system_call) syscall_exit_work:
testl $_TIF_WORK_SYSCALL_EXIT, %ecx
jz work_pending
END(syscall_exit_work) work_pending:
testb $_TIF_NEED_RESCHED, %cl
jz work_notifysig
work_resched:
call schedule
jz restore_all
work_notifysig:
... ; deal with pending signals
END(work_pending)

  无论是中断返回(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对于系统调用的汇编具体代码是不一样的。

三、总结

(1)open 函数通过系统调用号与 sys_open 系统调用服务例程函数联系起来

(2)int 0x80 通过中断向量(0x80)与 system_call 联系起来的

(3)系统调用中断本质上是一个保存当前工作状态,然后处理,最后返回并且恢复进程的过程

刘帅

原创作品转载请注明出处

《Linux内核分析》MOOC课程

Linux内核分析之扒开系统调用的三层皮(下)的更多相关文章

  1. 《Linux内核分析》--扒开系统调用的三层皮 20135311傅冬菁

    扒开系统调用的三层皮           20135311傅冬菁 一.内容分析 寄存器上下文(从用户态切换到内核态) 中断/int指令会在堆栈上保存一些寄存器的值(用户态栈顶地址..当时的状态字.当下 ...

  2. Linux内核分析之扒开系统调用的三层皮(上)

    一.原理总结 本周老师讲的内容主要包括三个方面,用户态.内核态和中断,系统调用概述,以及使用库函数API获取系统当前时间.系统调用是操作系统为用户态进程与硬件设备进行交互提供的一组接口,也是一种特殊的 ...

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

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

  4. linux 内核 第四周 扒开系统调用的三层皮 上

    姬梦馨 原创作品 http://mooc.study.163.com/course/USTC-1000029000 一.用户态.内核态和中断处理过程 用户通过库函数与系统调用联系起来:库函数帮我们把系 ...

  5. 《Linux内核分析》第四周 扒开系统调用的“三层皮”

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FOUR( ...

  6. 《Linux内核分析》第五周 扒开系统调用的三层皮(下)

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FIVE( ...

  7. LINUX内核分析第五周学习总结——扒开系统调用的“三层皮”(下)

    LINUX内核分析第五周学习总结--扒开系统调用的"三层皮"(下) 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>M ...

  8. 《Linux内核分析》第五周学习总结 扒开系统调用的三层皮(下)

    扒开系统调用的三层皮(下) 郝智宇 无转载 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.给Men ...

  9. 《Linux内核分析》 第四节 扒开系统调用的三层皮(上)

    <Linux内核分析> 第四节 扒开系统调用的三层皮(上) 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com ...

随机推荐

  1. Mybatis之关联查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  2. 【Python全栈笔记】04 [模块二] 18 Oct lambda表达式, 内置函数

    lambda表达式 lambda表达式是函数的一种简化,如下面两种函数定义方法,实际上效果是一样的. 使用lambda表达式的函数,func2是函数名,lambda: 后面的123 即为返回值. de ...

  3. instruments usage error specified target process is invalid

    遇到这个问题的很多,但都没说具体的解决办法. 如果你的包名 路径之类的都正确,还是报这个错误的话,请重启手机.

  4. List集合基于某个字段排序

    using System; using System.Collections.Generic; namespace ConsoleApplication1 { class Product { publ ...

  5. MD5编码的内存泄露

    MD5CryptoServiceProvider 如果多次使用会产生内存溢出,如下这样调用几百万次就会出现内存 溢出. public static string MD5Encode(string so ...

  6. 重启eclipse color theme失效的解决办法

    For Eclipse Mars users: In the main menu bar, go to Window > Preferences In the preference tree o ...

  7. 漫谈Linux内核哈希表(1)

    关于哈希表,在内核里设计两个很重要的数据结构:    哈希链表节点: 点击(此处)折叠或打开 .x [include/linux/types.h]*/ struct hlist_node { stru ...

  8. 总结下用Vue.js和webpack遇到的问题

    这段时间用vue.js+webpack做一个单页应用的demo,第一次尝试模块化,技术水平有限,学习不够深入,总是遇到各种问题,所谓前事不忘后事之师,so记录下. 1.ES6匿名函数里面this值 结 ...

  9. WampServer3.0.4 允许外网访问配置教程

    原文地址:http://jingyan.baidu.com/album/acf728fd556c93f8e410a344.html?picindex=1

  10. SGA(System Global Area)

    系统激活时在内存内规划的一个固定的区域,用于存储每位使用者所需存取的数据和必备的系统信息.这个区域成为系统全局区. 数据块缓存区:存放读取数据文件的数据块副本,或者曾经处理过的数据.有效减少读取数据时 ...