一.分析system_call中断处理过程

实验

下载最新menu,并在test.c中增加mkdir与mkdir-asm函数原型

rm menu -rf
git clone https://github.com/mengning/menu.git
cd menu
vim test.c

增加下面的代码:

int Mkdir(int argc,char *argv[]){
if(mkdir(argv[1],S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0)
printf("New dir successfully!\n");
else
printf("New dir failed!\n");
return 0;
}
int MkdirAsm(int argc,char *argv[]){
int intr;
mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
__asm__ __volatile__(
"int $0x80;\n\t"
: "=a" (intr)
: "a"(39),"b"(argv[1]),"c"(mode)
:"memory"
);
if(intr == 0)
printf("New dirasm successfully!\n");
else
printf("New dirasm failed!\n");
return 0;
}

有两点需要强调,这也是我实验过程中出现过问题,才改进之后的代码!

  • 注意加头文件#include <sys/stat.h> #include <sys/types.h>
  • mkdir系统调用的结果是创建一个目录,而MenuOS并没有ls这个命令,所以为了验证我们添加mkdir和mkdir-asm命令成功,必须在函数中添加相应的判断与输出的语句,所以与上次实验代码相比,这里多了if与else语句和printf语句。否则我们无法验证在MenuOS中命令是否执行成功。





    上面这个图我是先用mkdir创建了一个testdir目录,显示创建成功;随后我又用mkdir-asm又创建testdir这个目录,因为这个目录刚才已经用mkdir创建过,所以必然失败,这也变相说明上一步mkdir创建成功;随后我又用mkdir-asm创建了testdir1,显示创建成功。

    下一步进行gdb调试:
cd ..
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S //启动并“冰冻”
gdb linux-3.18.6/vmlinux
target remote:1234 //连接到刚启动的虚拟机



上图为b start_kernel之后的结果。

根据39号系统调用的内核函数sys_mkdir,执行b sys_mkdir



结果系统停在了启动的“半路上”。并不是像断sys_time那样。很显然,这说明在内核启动过程中,必然要调用sys_mkdir该系统调用(虽然我现在还不知道有哪些过程要调用它,但可以肯定的是一定有过程调用它!)。

还得出一条心得就是实验楼环境是真的不好用,每当我把当前界面换到启动的虚拟机,则必然造成死机。只有重新开始实验,这样造成的结果就是我还得重新下载menu,重新编写test.c。不仅如此,还无法实施对mkdi与mkdir-asm的跟踪,因为一切换到MenuOS就卡掉了,根本没法输入命令。

总结

system_call到iret之间的简化后伪代码:

ENTRY(system_call)
SAVE_ALL
syscall_call:
call *sys_call_table(,%eax,4)
movl %eax,PT_EAX(%eax) //保存返回值
syscall_exit:
testl $_TIF_ALLWORK_MASK,%ecx //current—>work
jne syscall_exit_work
restore_all:
RESTORE_INT_REGS
irq_return:
INTERRUPT_PETURN
ENDPROC(system_call)
syscall_exit_work:
testl $_TIF_WORK_SYSCALLEXIT,%ecx
jz work_pending
END(syscall_exit_work)
work_pending:
testb $_TIF_NEED_RESCHED,%c1
jz work_notifysig
work_resched:
call schedule
jz restore_all
work_notifysig:
...
END(work_pending)

流程图:



简化后的伪代码中只留下了一部分重要代码。比如对系统调用结束时要做的工作,这里只留下了两个判断,一个是是否有需要处理的信号,如果有,那就跳到相应的处理入口地址;第二个是是否需要进程调用,如果有那就转去处理进程调用,如果没有就结束。其实我们浏览没有简化的代码会发现,在这个过程中还有判断是否发生异常及异常处理等代码。

二.课本第九、十章内核同步

临界区的引出

共享资源之所以要防止并发访问,是因为如果多个执行线程同时访问和操作数据,就有可能发生各个线程之间相互覆盖共享数据的情况,造成被访问数据处于不一致状态。而访问和操作共享数据的代码段就被称为临界区。所以两个执行中的线程不可能处于同一个临界区中共同执行,一个临界区在执行完之前不可被打断。

同步和互斥

互斥指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。

同步是散布在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。

加锁

如果有一个线程对共享的数据加锁,则其他的线程就不能再访问该共享数据,必须等解锁之后才能去访问。简而言之,对同一共享数据,特定时间内只有一个线程可以进入与该共享数据对应的临界区。

死锁

  • 若系统中存在一组进程(两个或多个进程),它们中的每一个进程都占用了某种资源而又都在等待其中另一个进程所占用的资源,这种等待永远不能结束,则说系统出现了“死锁”。或说这组进程处于“死锁”状态。
  • 死锁产生的必要条件
    • 互斥使用资源
    • 占有并等待资源
    • 不可抢夺资源
    • 循环等待资源
  • 解决死锁的办法就是打破上述一个或多个必要条件。

自旋锁

自旋锁最多只能被一个可执行线程持有,如果一个执行线程试图获得一个被已经持有的自旋锁,那么该线程就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求锁的执行线程便能立刻得到它们继续执行。在任意时间,自旋锁都可以防止多于一个的执行线程同时进入临界区。同一个锁可以用在多个位置。

信号量

  • 计数信号量,比如读者-写者问题中的读者的数量。
  • 二值信号量,比如读者-写者问题中对读者数量count的访问。

BLK:大内核锁

BLK是一个全局自旋锁,使用它主要是为了方便Linux最初的SMP过度到细粒度加锁机制。

  • 持有BLK的任务仍然可以睡眠。
  • BLK是一种递归锁。
  • BLK只可用在进程上下文中。
  • 新的用户不允许使用BLK。

2017-2018-1 20179209《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. HDFS Scribe Integration 【转】

    It is finally here: you can configure the open source log-aggregator, scribe, to log data directly i ...

  2. Single Number III - LeetCode

    Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

  3. 各语言最原始数据库访问组件封装DBHelper

    源码:https://github.com/easonjim/DBHelper bug提交:https://github.com/easonjim/DBHelper/issues 每个语言放在不同的分 ...

  4. ThinkPHP 中M方法和D方法的具体区别

    M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...

  5. EasyMvc入门教程-基本控件说明(13)选项卡导航

    选项卡Tab导航主要用于企业页面显示不同子类或者子页面的信息内容. 先来一个基本的使用例子:代码如下: @{ var data = new List<TabItem>() { new Ta ...

  6. Dapper Sqlpara where in

    Mark一下:string sql = "SELECT * FROM SomeTable WHERE id IN @ids" var results = conn.Query(sq ...

  7. C#自定义MessageBox 按钮的Text

    运行效果: 代码: using System; using System.Drawing; using System.Runtime.InteropServices; using System.Tex ...

  8. Spring3和Quartz2的应用实例

    /** * 任务调度类 * @author Joyce.Luo * @date 2015-3-31 下午03:32:04 * @version V3.0 * @since Tomcat6.0,Jdk1 ...

  9. 点击页面li显示li中文字

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  10. H5和CSS3新增内容总结

    CSS3选择器有哪些?答:属性选择器.伪类选择器.伪元素选择器.CSS3新特性有哪些?答:1.颜色:新增RGBA,HSLA模式 文字阴影(text-shadow.) 边框: 圆角(border-rad ...