一.基于时间片轮转调度代码的解读

代码结构主要由三个文件组成:

1.mypcb.h

2.myinterrupt.c

3.mymain.c

1.进程控制块(mypcb.h)

/* CPU-specific state of this task */
struct Thread{
unsigned long ip; //eip,程序入口地址
unsigned long sp; //堆栈esp栈顶地址
}; typedef struct PCB{
int pid; //进程pid号
volatile long state; //进程运行状态,-1 unrunnable,0 runnable,>0 stopped
char stack[KERNEL_STACK_SIZE]; //进程的栈空间
/* CPU-specific state of this task */
struct Thread thread; //CPU的相关状态
unsigned long task_entry; //进程运行对应的函数
struct PCB *next; //下一个进程块地址
}tPCB; void my_schedule(void);

这里进程控制块(PCB)是采用链表的形式链接起来的。

2.进程的切换(myinterrupt.c)

extern tPCB task[MAX_TASK_NUM]; //进程控制块数组
extern tPCB *my_current_task; //当前对应的进程控制块
extern volatile int my_need_sched; //标志字段,来表示是否需要对进程进行调度 //时钟中断,周期性调用这个函数
void my_timer_handler(void){
#if 1
if(time_count%== && my_need_sched!=){
printk(KERN_NOTICE">>>my_timer_handler here<<<\n");
my_need_sched=;
} time_count++;
#endif
return;
}

接下来是进程上下文切换最关键的代码(my_schedule函数),采用的是内嵌汇编代码

当下一个进程的状态是正在运行时,则

if(next->state==){// -1 unrunnable,0 runnable,>0 stopped
/*switch to next process */
asm volatile(
"pushl %%ebp\n\t" //保存当前进程的栈基址指针 ebp
"movl %%esp,%0\n\t" //保存当前进程的栈顶指针 esp
"movl %2,%%esp\n\t" //回复下一个进程的栈顶指针 esp
"movl $1f,%1\n\t" //将当前进程的下一个指令地址保存到thread.ip中
"pushl %3\n\t" //将下一个进程的指令执行地址入栈
"ret\n\t" //ip出栈,
"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)
);
}

若下一个进程是新的进程,还没有执行过,基本方式与上面差不多,也是基于内嵌汇编方式实现上下文切换。

3.内核代码运行(mymain.c)

 内核从my_start_kernel开始执行,my_start_kernel主要是进行进程控制块的初始化,同时启动0号进程。

void __init my_start_kernel(void)
{
int pid = ;
int i;
/* Initialize process 0*/
task[pid].pid = pid;
task[pid].state = ;/* -1 unrunnable, 0 runnable, >0 stopped */
task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;
task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-];
task[pid].next = &task[pid];
/*fork more process */
for(i=;i<MAX_TASK_NUM;i++)
{
memcpy(&task[i],&task[],sizeof(tPCB));
task[i].pid = i;
task[i].state = -;
task[i].thread.sp = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-];
task[i].next = task[i-].next;
task[i-].next = &task[i];
}
/* start process 0 by task[0] */
pid = ;
my_current_task = &task[pid];
asm volatile(
"movl %1,%%esp\n\t" /* set task[pid].thread.sp to esp */
"pushl %1\n\t" /* 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*/
);
}

然后0号进程开始执行my_process函数。

4.程序运行的结果

二.实验总结

通过完成这个简单的时间片轮转多道程序的实验,让我更加深刻的理解了进程上下文切换的原理,以及内核启动的初始化过程。

《Linux内核分析》 week2作业-时间片轮转的更多相关文章

  1. 《linux内核分析》作业一:分析汇编代码

    通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的(王海宁) 姓名:王海宁                             学号:20135103 课程:<Linux内核分析& ...

  2. Linux内核分析

    通过分析汇编代码理解计算机是如何工作的   网易云课堂<Linux内核分析>作业 实验目的: 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 实验过程: 登陆实验楼虚拟机h ...

  3. 分析Linux内核中进程的调度(时间片轮转)-《Linux内核分析》Week2作业

    1.环境的搭建: 这个可以参考孟宁老师的github:mykernel,这里不再进行赘述.主要是就是下载Linux3.9的代码,然后安装孟宁老师编写的patch,最后进行编译. 2.代码的解读 课上的 ...

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

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

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

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

  6. Linux内核启动分析过程-《Linux内核分析》week3作业

    环境搭建 环境的搭建参考课件,主要就是编译内核源码和生成镜像 start_kernel 从start_kernel开始,才真正进入了Linux内核的启动过程.我们可以把start_kernel看做平时 ...

  7. Linux内核分析作业 NO.2

    操作系统是如何工作的 于佳心 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  ...

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

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

  9. Linux内核分析作业第二周

    操作系统是如何工作的 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈 1.计算机工作三 ...

  10. Linux内核分析作业二

    贾瑗 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  一.操作系统是如 ...

随机推荐

  1. 脚本两则--用于快速部署HADOOP,SPARK这些(特别是VM虚拟机模板部署出来的)。。

    感觉可能只是适合我自己的部署习惯吧,且只针对CENTOS6及以下版本,以后有时间,可能还是要改进.. 1,从VM的模块产生的虚拟机,如何快速搞定网络配置? #!/bin/bash #usage:./i ...

  2. Understanding GC pauses in JVM, HotSpot's minor GC.

    原文地址:http://blog.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots.html Stop-the-worl ...

  3. PBOC规范研究

    一.ISO14443协议和PBOC关于CID的约定 看过协议的人其实都明白,RATS命令中参数字节的低半字节是CID,期中,CID不能为15. ISO14443协议中要求当RATS命令的CID等于0时 ...

  4. Keil C51总线外设操作问题的深入分析

    阅读了<单片机与嵌入式系统应用>2005年第10期杂志<经验交流>栏目的一篇文章<Keil C51对同一端口的连续读取方法>(原文)后,笔者认为该文并未就此问题进行 ...

  5. 理解使用static import 机制(转)

    J2SE 1.5里引入了“Static Import”机制,借助这一机制,可以用略掉所在的类或接口名的方式,来使用静态成员.本文介绍这一机制的使用方法,以及使用过程中的注意事项. 在Java程序中,是 ...

  6. 【细说Java】方法重载的简单介绍

    1. 什么是重载 方法名称相同,但它们的参数类型或个数不同,这样,方法在被调用时编译器就可以根据参数的类型与个数的不同加以区分,这就是方法的重载. 既然可以通过参数类型或参数个数来作为重载条件,那返回 ...

  7. javascript正则表达式(二)——方法

    正则表达式规则见:http://www.cnblogs.com/wishyouhappy/p/3756812.html,下面说明相关方法 String相关方法 概括: search() replace ...

  8. .net Web.Config配置文件 转

    .net Web.Config配置文件 博客分类: .net   .net Web.Config配置文件 一.配置信息 <?xml version="1.0" encodin ...

  9. R语言笔记

    R语言笔记 学习R语言对我来说有好几个地方需要注意的,我觉得这样的经验也适用于学习其他的新的语言. 语言的目标 我理解语言的目标就是这个语言是用来做什么的,为什么样的任务服务的,也就是设计这个语言的动 ...

  10. XSLT学习

    XSL 语言 XSL(eXtensible Stylesheet Language)是可扩展样式表语言,是一种用于以可读格式呈现 XML(标准通用标记语言的子集)数据的语言. XSL与xml CSS ...