实验

给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. Saltstack之multi-master

    一.实验环境: 1.salt版本: [root@master master]# salt --versions-report Salt: 2015.5.10 Python: 2.7.5 (defaul ...

  2. 【转载】Windows下VSCode编译调试c/c++

    懒得自己配置或自己配置出现不明问题的朋友可以点这里: [VSCode]Windows下VSCode便携式c/c++环境 http://blog.csdn.net/c_duoduo/article/de ...

  3. 轻松实现Android,iOS的一个手势动画效果

    先来看效果 这是iOS下的效果,android下完全一致.通过do_GestureView组件和do_Animation组件,deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过 ...

  4. The Bottom of a Graph-POJ2553强连通

    The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 9759 Accepted: 4053 ...

  5. 显示Class 'Think\Controller\FuController' not found和Call to a member function assign() on a non-object 的错误问题

    Class 'Think\Controller\FuController' not found 错误位置 FILE: D:\wamp\www\tinkphp\Application\Come\Cont ...

  6. Java读取Level-1行情dbf文件极致优化(2)

    最近架构一个项目,实现行情的接入和分发,需要达到极致的低时延特性,这对于证券系统是非常重要的.接入的行情源是可以配置,既可以是Level-1,也可以是Level-2或其他第三方的源.虽然Level-1 ...

  7. H2数据库攻略

    H2是一个开源的嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个十分方便的web控制台用于操作和管理数据库内容.H2还提供兼容模式,可以兼容一些主流的数据库,因此采用H2作为 ...

  8. sqlalchemy中文乱码问题解决方案

    本文参考http://firefish.blog.51cto.com/298258/112794/的解决方案 问题: 本文在Ubuntu上利用scrapy抓取数据写入mysql数据库时,用到sqlal ...

  9. Swift基础语法学习总结(转)

    Swift基础语法学习总结 1.基础  1.1) swift还是使用// 和/* */ 来注释,并且/* */允许多行注释. 1.2) swift使用print和println打印,它的传参是一个泛型 ...

  10. dubbo配置文件报错解决方案

    下载dubbo.xsd 文件 在eclipse->window->perferences->XML Catalog->Add ->File system->选择刚才 ...