一个简单的时间片轮转多道程序内核代码及分析

所用代码为课程配套git库中下载得到的。

一、进程的启动

/*出自mymain.c*/
/* start process 0 by task[0] */
pid = 0;
my_current_task = &task[pid];
asm volatile(
"movl %1,%%esp\n\t" /* 将进程的sp赋给esp寄存器 */
"pushl %1\n\t" /* ebp入栈:因为在这里栈为空,esp=ebp,所以push的%1就是esp就是ebp。*/
"pushl %0\n\t" /* 进程入口ip入栈 */
"ret\n\t" /* 把进程入口ip赋给eip,即从这之后0号进程启动。*/
"popl %%ebp\n\t"
:
: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/
);

二、进程的切换

进程的切换有两种:

1.下一个进程next->state == 0 即正在执行时

/*出自myinterrupt.c*/
//两个正在运行的进程之间做进程上下文切换 if(next->state == 0)
/* state值的含义:-1表示没有执行,0表示正在执行,>0表示停止,这里为0,即进程正在执行 */
{
/* 以下是进程切换关键代码 */
asm volatile(
"pushl %%ebp\n\t" /* 把当前进程的ebp保存*/
"movl %%esp,%0\n\t" /* 把当前进程的esp赋值到sp中保存下来*/
"movl %2,%%esp\n\t" /* 把下一个进程的sp放到esp中*/
"movl $1f,%1\n\t" /* 把eip保存起来,$1f指接下来的标号1:的位置*/
"pushl %3\n\t" /*把下一个进程的eip保存起来*/
"ret\n\t" /* 还原eip */
"1:\t" /* 标号1,下一进程从此开始 */
"popl %%ebp\n\t"
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);
my_current_task = next;
printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);
}

2.进程是一个新进程,还从未执行过

/*出自myinterrupt.c*/
/*这段代码是当进程从未执行过时,所执行的动作,即启动一个进程 next->state = 0; /* 首先要把进程置为运行时状态,作为当前正在执行的进程 */
my_current_task = next;
printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);
/* 进程切换时的提示,从当前进程切换至下一进程*/
asm volatile( //混合编程
"pushl %%ebp\n\t" /* 保存ebp */
"movl %%esp,%0\n\t" /* 保存esp */
"movl %2,%%esp\n\t" /* 将下一进程的sp存入esp */
"movl %2,%%ebp\n\t" /* 将下一进程的bp存入ebp,因为栈空,所以esp和ebp指向同一位置 */
"movl $1f,%1\n\t" /* 保存eip */
"pushl %3\n\t" /*保存当前进程入口 */
"ret\n\t" /* 还原eip */
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);

三、实验截图

这个实验我是根据github中的步骤,在自己虚拟机中一点点做的,最后成功做出来了,截图如下:

四、操作系统是如何工作的

就像计算机有三件法宝一样,操作系统也有“两把剑”,分别是中断上下文进程上下文的切换

有了中断后,就有了多道程序设计,每个程序有自己的执行流,中断发生时,cpu把当前的eip等压入内核堆栈中,然后把eip指向中断处理程序的入口。

在模拟操作系统的代码里可以看出,mypcb.h中定义了结构体,用于存放sp和ip,以及pcb块,每个pcb块就是一个进程。

然后在mymain.c中,先创建了几个进程,具体创建过程见上。

然后设立一个循环,比如循环一百万次再来判定是否需要调度,这是建立了一个主动的调度机制,对应的是这个函数:

void my_process(void)
{
int i = 0;
while(1)
{
i++;
if(i%10000000 == 0)
{
printk(KERN_NOTICE "this is process %d -\n",my_current_task->pid);
if(my_need_sched == 1)//执行一千万次才判断是否需要调度。有一个主动调度的机制。
{
my_need_sched = 0;
my_schedule();
}
printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid);
}
}
}

有调度就要有进程的的切换,切换也在上面说过了。

因为是时间片轮转,所以需要设立一个时间片,当时间片用尽时设立调度标志,如下:

void my_timer_handler(void)
{
#if 1
//设置时间片的大小,时间片用完时设置一下调度标志。
if(time_count%1000 == 0 && my_need_sched != 1)
{
printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");
my_need_sched = 1;
}
time_count ++ ;
#endif
return;
}

总体思路就是时间片用尽时设置调度标志,然后判断是否需要调度用一个无限循环控制,需要调度了就切换进程。

最后附上这周的=学习笔记

**闫佳歆 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 **

20135202闫佳歆--week2 一个简单的时间片轮转多道程序内核代码及分析的更多相关文章

  1. Linux内核分析—完成一个简单的时间片轮转多道程序内核代码

    ---恢复内容开始--- 20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10 ...

  2. Linux内核分析:完成一个简单的时间片轮转多道程序内核代码

    PS.贺邦   原创作品转载请注明出处  <Linux内核分析>MOOC课程    http://mooc.study.163.com/course/USTC-1000029000 1.m ...

  3. Linux内核分析第二周学习博客——完成一个简单的时间片轮转多道程序内核代码

    Linux内核分析第二周学习博客 本周,通过实现一个简单的操作系统内核,我大致了解了操作系统运行的过程. 实验主要步骤如下: 代码分析: void my_process(void) { int i = ...

  4. linux内核分析第二周-完成一个简单的时间片轮转多道程序内核代码

    中断时计算机运行的一个非常重要的功能.之所以重要,是因为由于种种原因,计算机不能将一个程序从头执行到尾不间断,而是可能会出现很多像等待输入设备输出设备的过程,如果没有中断系统,CPU只能等待,造成资源 ...

  5. linux内核分析作业:操作系统是如何工作的进行:完成一个简单的时间片轮转多道程序内核代码

    计算机如何工作 三个法宝:存储程序计算机.函数调用堆栈.中断机制. 堆栈 函数调用框架 传递参数 保存返回地址 提供局部变量空间 堆栈相关的寄存器 Esp 堆栈指针  (stack pointer) ...

  6. Linux内核设计第二周学习总结 完成一个简单的时间片轮转多道程序内核代码

    陈巧然 原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.使用实验楼的虚拟机 ...

  7. 20135202闫佳歆--week2 操作系统是如何工作的--学习笔记

    此为个人学习笔记存档 week 2 操作系统是怎么工作的 一.计算机是如何工作的?--三个法宝 (一)三个法宝 1.存储程序计算机 所有计算机的基础性的逻辑框架. 2.函数调用堆栈 在低级语言中并不很 ...

  8. 20135202闫佳歆--week 7 Linux内核如何装载和启动一个可执行程序--实验及总结

    week 7 实验:Linux内核如何装载和启动一个可执行程序 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.git c ...

  9. 20135202闫佳歆--week6 分析Linux内核创建一个新进程的过程——实验及总结

    week 6 实验:分析Linux内核创建一个新进程的过程 1.使用gdb跟踪创建新进程的过程 准备工作: rm menu -rf git clone https://github.com/mengn ...

随机推荐

  1. div+css ie6图片之间有间隙的问题

    图片转换为快级元素就解决了 img{display:block;} 也可设置img属性img{vertical-align:top;}

  2. node学习笔记_01 环境搭建

    一.下载安装nvm (node版本管理器),方便以后版本切换 nvm list            -> 查看node版本(版本最好在8.0以上,不然在vsCode断点调试进不去,跟node版 ...

  3. 为什么说swift是面向协议编程--草稿

    为什么说swift是面向协议编程 public protocol ReactiveCompatible { /// Extended type associatedtype CompatibleTyp ...

  4. [Luogu 3707] SDOI2017 相关分析

    [Luogu 3707] SDOI2017 相关分析 前言 Capella 和 Frank 一样爱好天文学. 她常在冬季的夜晚,若有所思地望着东北方上空的五边形中,最为耀眼的一个顶点. 那一抹金黄曾带 ...

  5. IIS7.5全站301跳转,内页+带参数url,这才是真正的全站跳转

    说好的转型安全领域,可是我还是忍不住要给大家分享这个教程.因为这个问题很常见,大部分人都遇到了(可能你没注意),困扰了我很久,相信这是一篇真正适合你的IIS301跳转教程. 背景 说到301跳转,作为 ...

  6. 2.2.1 LinearLayout(线性布局)

    本节引言 本节开始讲Android中的布局,Android中有六大布局,分别是: LinearLayout(线性布局), RelativeLayout(相对布局), TableLayout(表格布局) ...

  7. 7、JVM--虚拟机类加载机制

    7.1.概述 再类文件结构中 在Class文件中描述的各种信息,最终都需要加载到虚拟机中之后才能运行和使用. 而虚拟机如何加载这些Class文件?Class文件中的信息进入到虚拟机后会发生什么变化? ...

  8. servlet3.0

    1.之前我们创建的项目是servlet2.5,之前的版本,servlet.filter.listener需要配置web.xml 在servlet3.0的时候,没有web.xml,提供注解开发. ser ...

  9. 几个PHP读取整个文件的函数readfile()、fpassthru()和file()

    2.7.4   读取整个文件:readfile().fpassthru()和file()除了可以每次读取文件一行外,还可以一次读取整个文件.PHP提供了4种不同的方式来读取整个文件.第一种方式是rea ...

  10. 在 R 中估计 GARCH 参数存在的问题(续)

    目录 在 R 中估计 GARCH 参数存在的问题(续) rugarch 包的使用 简单实验 rugarch 参数估计的行为 极端大样本 结论 在 R 中估计 GARCH 参数存在的问题(续) 本文承接 ...