实验

给MenuOS增加time和time-asm命令的方法:

  1. 更新menu代码到最新版
  2. 再main()函数中增加MenuConfig
  3. 增加对应的Time函数和TimeAsm函数(这里的函数要换成我们自己编写的使用系统调用的函数,比如mkdir和mkdirAsm)
  4. make rootfs (帮我们自动编译自动生成根文件系统,自动帮我们启动起来menuos)

接下来我要使用gdb跟踪分析一个系统调用内核函数(mkdir)

这次我实验所用的系统调用仍然是是mkdir

首先,我们需要把上周做的两个实验加入到我们的MenuOS中,变成MenuOS中的两个命令。如图:

方法是要将函数加入到test.c中(因为实验楼中的clone无法使用),加入命令为:

int Mkdir()
{
int flag;
flag = mkdir("/home/shiyanlou/testdir");
if (flag == -1)
printf("mkdir failed!\n");
else
printf("make dirctory success!\n");
return 0;
} int MkdirAsm()
{
int flag;
char *dir = "/home/shiyanlou/testdir2";
asm volatile(
"movl $0x27,%%eax\n\t"
"movl %1,%%ebx\n\t"
"int $0x80\n\t"
"movl %%eax,%0\n\t"
:"=m"(flag)
:"c"(dir)
);
if(flag==0)
printf("mkdir success!\n");
else
printf("mkdir failed!\n");
return 0;
}

在main函数中加入:

    MenuConfig("mkdir","Make A Directory",Mkdir);
MenuConfig("mkdir-asm","Make A Directory(asm)",MkdirAsm);

make rootfs就可以自动生成,输入help可以看到mkdir,如下结果:

下面开始用gdb调试:

cd LinuxKernel
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
水平分割
gdb
file linux-3.18.6/vmlinux //加载内核
target remote:1234 //链接到menu os里
b start_kernel //在start_kernel处设置断点
c //继续执行,到start_kernel 停下来

list                        //查看startkernel这段代码
b sys_mkdir //在我们要分析的这个系统调用处设置断点
c //继续执行
c
c

启动menuos,输入mkdir,看gdb调试结果

如果我们换用视频里的sys_time设置断点进行调试,之前的方法与mkdir类似,然后可以继续跟踪调试如下:

b sys_time
c
c
c
list
s //单步执行
s //单步执行
finish //函数执行完
s
s
n
n

这边代码就不大好调试了,如果我们再设置一个断点,当我们用int 0x80时,cpu自动跳转到system_call这个函数,下面我们直接设置断点system_call,是否能停下来呢?

b system_call
c

发现time返回了。在menuos中输入time—asm,停在system_time的位置,system_call并不能停下。老师说这里的system_call他不是一个正常的函数,它是一段特殊的汇编代码,可能gdb对他不支持,我们只能调试系统调用函数和对应的内核函数,调试内核函数的处理过程,但不能跟踪entry_32.s这个汇编代码,在system_call处并没有停下来。system_call在entry_32.s中,可以找到ENTRY(system_call),gdb可以发现一个函数原型,实际上不是函数,是汇编代码的起点,gdb现在还不能跟踪它。

关于从system_call到iret之间的过程

画了一个大致的流程图,如下:



首先保护现场(SAVE_ALL:保存需要用到的寄存器数据);退出恢复现场(RESTORE_ALL:退出中断程序,恢复保存寄存器的数据)。

下面为SAVE_ALL的实现:

.macro SAVE_ALL
cld
PUSH_GS
pushl_cfi %fs
/*CFI_REL_OFFSET fs, 0;*/
pushl_cfi %es
/*CFI_REL_OFFSET es, 0;*/
pushl_cfi %ds
/*CFI_REL_OFFSET ds, 0;*/
pushl_cfi %eax
CFI_REL_OFFSET eax, 0
pushl_cfi %ebp
CFI_REL_OFFSET ebp, 0
pushl_cfi %edi
CFI_REL_OFFSET edi, 0
pushl_cfi %esi
CFI_REL_OFFSET esi, 0
pushl_cfi %edx
CFI_REL_OFFSET edx, 0
pushl_cfi %ecx
CFI_REL_OFFSET ecx, 0
pushl_cfi %ebx
CFI_REL_OFFSET ebx, 0
movl $(__USER_DS), %edx
movl %edx, %ds
movl %edx, %es
movl $(__KERNEL_PERCPU), %edx
movl %edx, %fs
SET_KERNEL_GS %edx
.endm

在这段代码中,保存了相关寄存器的值。 他们依次是:ES,DS,EAX,EBP,EDI,ESI,EDX,ECX,EBX等等。从这里寄存器的顺序可以知道压栈的最后压入的是ebx,这里压入的栈是内核栈。

遇到的问题

  1. 在使用实验楼clone的时候出现问题,后将test.c文件更改进行解决
  2. 实验楼一直很卡,试验了好多次最后在MenuOs上输入的mkdir命令上还是卡住了

书上的内容整理

  1. 内核同步介绍:留意保护共享资源,防止共享资源并发访问,发生各个线程之间相互覆盖共享数据的情况,造成访问数据不一致;临界区和竞争条件,临界区:访问和操作共享数据的代码段。 竞争条件:两个执行线程处于同一个临界区中;内核各个部分都会调用两个函数,一个函数将新请求添加到队列尾部,另一个函数从队列头删除请求,然后处理它。
  2. 锁的使用是自愿的、非强制的,它完全属于一种编程者自选的编程手段;内核中造成并发的原因:(1)中断:任何时刻异步发生,打断当前执行的代码(2)软中断和tasklet:任何时刻唤醒或调度软中断、tasklet(3)内核抢占(preempt)(4)睡眠及与用户空间的同步:唤醒调度程序,调度新进程执行(5)对称多处理器(SMP);编程需注意的问题: (1)数据是否全局?除了当前线程,其他线程是否可以访问? (2)数据是否在进程/中断上下文中共享?是否在两个不同中断中共享?(3)进程在访问数据时可否被抢占?被调度的新进程是否会访问同一数据? (4)当前进程是否会睡眠(阻塞)在某些资源上?共享数据处于何种状态? (5)怎样防止数据失控?;加锁:按顺序加锁。使用嵌套锁必须以相同顺序获取锁;防止发生饥饿; 不要重复请求同一个锁; 设计力求简单;建议以获取锁相反的顺序来释放锁。
  3. 原子操作:原子操作执行过程不被打断,原子操作接口分为整数操作接口和单独位操作接口。
  4. 自旋锁:自旋锁最多只能被一个可执行线程持有。若一个线程试图获得一个被征用的自旋锁,线程会一直忙循环、选择、等待锁可用。缺点:由于自旋锁在等待时自旋(浪费处理器时间),因此自旋锁不应长时间持有。优点:线程不用睡眠,不用进行上下文切换。自旋锁可以使用在中断处理程序中。对于软中断,无论是否同种类型,如果数据被软中断共享,那么它必须得到锁的保护。读写自旋锁:读写不同锁,多人和可并发持有读者锁,写锁只能被一个任务持有。
  5. 信号量特点: Linux中的信号量是一种睡眠锁; 信号量适用于锁会被长期占有的情况;

    由于信号量会睡眠,所以只能用于进程上下文中,中断上下文不支持调度;可以在持有信号量时睡眠; 不可以在持有信号量时使用自旋锁; 信号量允许任意数目的锁持有者,自旋锁一个时刻只允许一个任务持有;在声明时课指定信号量拥有的持有者数量。
  6. 禁止抢占:内核代码使用自旋锁作为非抢占区域的标记。preempt_disable() 增加抢占计数值,从而禁止内核抢占;preempt_enable() 减少抢占计数值,当减为0时检查和执行被挂起的任务; preempt_count() 返回抢占计数。

20169212《Linux内核原理与分析》第七周作业的更多相关文章

  1. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  2. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  3. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  4. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  5. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

  6. 2019-2020-1 20199329《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  10. 2018-2019-1 20189221《Linux内核原理与分析》第二周作业

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. 浅析Java.lang.Process类

    一.概述      Process类是一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序).      Process 类提供了执行从进程输入.执行输出到进程.等待进程完成.检查进程的 ...

  2. (更新)Java + 腾讯企业邮箱 + javamail + SSL 发送邮件

    咳咳~最头疼的就是莫名其妙的错误. 本来今年6月份运行通过的代码,过俩月就报错了. javax.mail.MessagingException: Could not connect to SMTP h ...

  3. java mkdir()和mkdirs()的区别

    boolean mkdir()    创建此抽象路径名指定的目录.   boolean mkdirs()    创建此抽象路径名指定的目录,包括创建必需但不存在的父目录. 也就是说,mkdir只能创建 ...

  4. Struts 笔记 内部资料 请勿转载 谢谢合作

    Struts 概述 随着MVC 模式的广泛使用,催生了MVC 框架的产生.在所有的MVC 框架中,出现最早,应用最广的就是Struts 框架. Struts 的起源 Struts 是Apache 软件 ...

  5. Android Paint的属性

    在Paint中有很多的属性可以设置,比如可以设置阴影,颜色过滤等等,这些会产生不同的奇妙效果,今天就对各种属性探索一下. 方法一: 1 //设置绘制的颜色,a代表透明度,r,g,b代表颜色值. 2 s ...

  6. this的问题

    javascript this可以绑定到:全局对象,自己定义的对象,用构造函数生成的对象,通过call或者apply更改绑定的对象    1.全局对象  1 2 3 4 5 function glob ...

  7. servlet上传下载(任何格式的都可以)

    jar不能低于此版本,JDK1.6以上,否则户报错 <dependency> <groupId>commons-fileupload</groupId> <a ...

  8. Dreamweaver架设网站终极教程

    转自:http://www.cnblogs.com/loveme513/archive/2006/04/03/365969.html 一.定义站点 1. 在任意一个根目录下创建好一个文件夹(我们这里假 ...

  9. Oracle(创建序列)

    概念: 所谓序列,在oracle中就是一个对象,这个对象用来提供一个有序的数据列,这个有序的数据列的值都不重复. 1.序列可以自动生成唯一值 2.是一个可以被共享的对象 3.典型的用来生成主键值的一个 ...

  10. 5.Swift枚举|结构体|类|属性|方法|下标脚本|继承

    1. 枚举: ->在Swift中依然适用整数来标示枚举值,需搭配case关键字 enum  Celebrity{  case DongXie,XiDu,Nandi,BeiGai }  // 从左 ...