操作系统是如何工作的

本章目标是在mykernel的基础上编写一个简单的内核

一、学习笔记

1.计算机的三个法宝:a.存储程序计算机;b.函数调用堆栈;c.中断

  • 存储程序计算机(所有计算机的基础性的逻辑框架);
  • 函数调用堆栈(C语言程序运行时必须使用的记录函数调用路径和参数存储的空间);
    • 堆栈具体的作用:

      • 记录函数调用框架
      • 传递函数参数
      • 保存返回值的地址
      • 提供函数内部局部变量的存储空间
    • 堆栈相关的寄存器:
      • ESP:堆栈指针
      • EBP:基址指针
    • 堆栈操作:
      • push:栈顶地址减少4个字节,并将操作数放进栈顶存储单元
      • pop:栈顶地址增加4个字节,并将栈顶存储单元的内容放入操作数
    • 其他关键寄存器:

      - CS:EIP:总是指向地址连续的下一条指令

      - 跳转/分支:执行这样的命令时,CS:EIP的值会根据程序需要被修改

      - call:将当前CS:EIP的值压入栈顶,CS:EIP指向被调用函数的入口地址

      - ret:从栈顶弹出原来保存在这里CS:EIP的值,放入CS:EIP



      - 堆栈特别关键的就是函数调用堆栈框架

二、实验

  • LinuxKernel/linux-3.9.4/mykernel目录下可以看到qemu窗口

    • 代码
cd LinuxKernel/linux-3.9.4
qemu -kernel arch/x86/boot/bzImage

- QEMU窗口

- 查看mymain.c



每循环10 000次,打印一句话。

- 查看myinterrupt.c



每执行一次,都会执行一次时钟中断。

下面是简单的时间片轮转机制内核代码:

mypcb.h

#define MAX_TASK_NUM 4

#define KERNEL_STACK_SIZE 1024*8

/* CPU-specific state of this task */

struct Thread {

unsigned long	ip;

unsigned long	sp;

};

typedef struct PCB{

int pid;

volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */

char stack[KERNEL_STACK_SIZE];
/* CPU-specific state of this task */ struct Thread thread; unsigned long task_entry; struct PCB *next; }tPCB; void my_schedule(void);
- 定义一个进程控制块pcb结构体
- task_entry:进程入口函数
- thread:保存eip和esp
- state:进程状态,用于判断是否调度

mymain.c

主要功能是让程序从0号进程开始运行,只列下面这段代码是核心。

asm volatile(

//%0表示参数thread.ip,%1表示参数thread.sp。

"movl %1,%%esp\n\t"     /* set task[pid].thread.sp to esp 把参数thread.sp放到esp中*/

"pushl %1\n\t"    /* push ebp 由于当前栈是空的,esp与ebp指向相同,所以等价于push ebp*/

"pushl %0\n\t"     /* push task[pid].thread.ip */

"ret\n\t"     /* pop task[pid].thread.ip to eip */

"popl %%ebp\n\t"

:

: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp)     /* input c or d mean %ecx/%edx*/

);

myinterrupt.c

主要功能是用于时钟中断处理和进程调度算法。

asm volatile(

"pushl %%ebp\n\t" /* save ebp 保存当前进程的ebp*/

"movl %%esp,%0\n\t" /* save esp 把当前进程的esp赋给%0(指的是thread.sp),即保存当前进程的esp*/

"movl %2,%%esp\n\t" /* restore esp 把%2(指下一个进程的sp)放入esp中*/

"movl $1f,%1\n\t" /* save eip $1f是接下来的标号“1:”的位置,把eip保存下来*/

"pushl %3\n\t" /*把下一个进程eip压栈*/

"ret\n\t" /* restore eip 下一个进程开始执行*/

"1:\t" /* next process start here */

"popl %%ebp\n\t"

: "=m" (prev->thread.sp),"=m" (prev->thread.ip)

: "m" (next->thread.sp),"m" (next->thread.ip)

);

三、总结

(1)进程和中断在操作系统是是非常重要的两个部分,需要熟练掌握。

(2)EIP寄存器储存着当前执行的代码,可以通过更改EIP寄存器的值来更改当前执行的代码,从而实现进程切换。出于安全考虑,EIP寄存器的值不能被直接改变,但可以通过压栈+ret指令来间接改变。

(3)进程在执行过程中,当时间片用完之后需要进程切换时,需要保存当前的执行上下文环境,下次被调度的时候,需要回复进程的上下文环境。

操作系统是如何工作的?

操作系统通过存储程序计算机机制依次执行程序的指令,堆栈为程序运行时录调用路径和参数提供空间,中断用于异常处理和进程调度。

2019-2020-1 20199301《Linux内核原理与分析》第三周作业的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  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. Swoole练习 安装

    仅支持 Linux,FreeBSD,MacOS,3类操作系统 Linux 内核版本 2.3.32 以上 PHP-5.3.10 以上版本,包括PHP7 gcc4.4 以上版本或者clang cmake2 ...

  2. Docker从容器内拷贝文件到主机上

    //以elasticsearch容器为例 //运行es docker run -d -p 9200:9200 elasticsearch:5.4 //查看已运行的容器 docker ps //进去容器 ...

  3. Tensorflow-逻辑斯蒂回归

    1.交叉熵 逻辑斯蒂回归这个模型采用的是交叉熵,通俗点理解交叉熵 推荐一篇文章讲的很清楚: https://www.zhihu.com/question/41252833 因此,交叉熵越低,这个策略就 ...

  4. memmove和memcpy函数的区别及实现

    一.memmove()和memcpy()函数和strcpy()函数的区别: (1)使用的类型不同,strcpy()函数只对字符串进行操作:memmove()和memcpy()函数对所有类型都适用,为内 ...

  5. 019 Android 形状可绘制对象(根据要求绘制图片)+图片选择器

    1.目标效果 绘制颜色渐变的图片 2.实现方法 (1)在app--->res--->drawable 右击drawable文件夹右键,new ---->drawable resour ...

  6. 多线程(8) — ThreadLocal

    ThreadLocal是一个线程的局部变量,也就是只有当前线程可以访问,是线程安全的.为每一个线程分配不同的对象,需要在应用层面保证ThreadLocal只起到简单的容器作用. ThreadLocal ...

  7. PAT(B) 1086 就不告诉你(Java)

    题目链接:1086 就不告诉你 (15 point(s)) 题目描述 做作业的时候,邻座的小盆友问你:"五乘以七等于多少?"你应该不失礼貌地围笑着告诉他:"五十三.&qu ...

  8. 封装函数(累计和、K型、金字塔)

    // 假设有个函数,只要传参数进去,就能统计累加的结果 function test($n){ if($n==1){ return 1; } return $n+test($n-1);}echo tes ...

  9. python练习:面向对象1

    面向对象习题: 一:定义一个学生类.有下面的类属性: 1 姓名 2 年龄 3 成绩(语文,数学,英语)[每课成绩的类型为整数] 类方法: 1 获取学生的姓名:get_name() 返回类型:str 2 ...

  10. python之(urllib、urllib2、lxml、Selenium+PhantomJS)爬虫

    一.最近在学习网络爬虫的东西,说实话,没有怎么写过爬虫,Java里面使用的爬虫也没有怎么用过.这里主要是学习Python的时候,了解到Python爬虫的强大,和代码的简介,这里会简单的从入门看是说起, ...