博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于mykernel的时间片轮转调度
阅读量:6204 次
发布时间:2019-06-21

本文共 4486 字,大约阅读时间需要 14 分钟。

学号: 363

原创作品,转载请注明出处。

本实验资源来源: 

 

一、 实验环境配置

本次实验在实验楼完成:

在实验楼的终端下输入下面命令:

cd LinuxKernel/linux-3.9.4rm -rf mykernelpatch -p1 < ../mykernel_for_linux3.9.4sc.patchmake allnoconfigmake qemu -kernel arch/x86/boot/bzImage

可查看运行结果

 关闭qemu窗口,进入mykernel文件夹,可以查看mymain.c和myinterrupt.c文件。

mymain.c的代码不断循环的去执行,周期性的产生时钟中断信号,去执行myinterrupt.c的代码。

 

二、实现时间片轮转多道程序

将mymain.c,myinterrupt.c,mypcb.h三个文件复制替换到mykernel文件夹下。

运行如下:

可以看到进程1切换到了进程2。

三、时间片轮转多道程序的代码分析

mypcb.h

/* *  linux/mykernel/mypcb.h * *  Kernel internal PCB types * *  Copyright (C) 2013  Mengning * */#define MAX_TASK_NUM        4#define KERNEL_STACK_SIZE   1024*2 # unsigned long/* 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 */    unsigned long 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中定义了pid,状态statue,线程thread,进程入口函数task_entry等.

 

mymain.c文件

/* *  linux/mykernel/mymain.c * *  Kernel internal my_start_kernel * *  Copyright (C) 2013  Mengning * */#include 
#include
#include
#include
#include
#include "mypcb.h"tPCB task[MAX_TASK_NUM];tPCB * my_current_task = NULL;volatile int my_need_sched = 0;void my_process(void);void __init my_start_kernel(void){ int pid = 0; int i; /* Initialize process 0*/ task[pid].pid = pid; task[pid].state = 0;/* -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-1]; task[pid].next = &task[pid]; /*fork more process */ for(i=1;i
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 __init my_start_kernel(void)这个函数fork了4个新进程,把新fork的进程加入到进程链表在这个文件中。

汇编过程如下:
(1)将0号进程的esp的值赋给ESP寄存器
(2)将0号进程的esp的值压栈(此时堆栈状态为进程0的堆栈)
(3)将0号进程的eip的值压栈
(4)通过ret指令,让栈顶的eip的值出栈到EIP寄存器中(间接改变EIP寄存器的值),完成进程0的启动

 

myinterupt.c

/* *  linux/mykernel/myinterrupt.c * *  Kernel internal my_timer_handler * *  Copyright (C) 2013  Mengning * */#include 
#include
#include
#include
#include
#include "mypcb.h"extern tPCB task[MAX_TASK_NUM];extern tPCB * my_current_task;extern volatile int my_need_sched;volatile int time_count = 0;/* * Called by timer interrupt. * it runs in the name of current running process, * so it use kernel stack of current running process */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; }void my_schedule(void){ tPCB * next; tPCB * prev; if(my_current_task == NULL || my_current_task->next == NULL) { return; } printk(KERN_NOTICE ">>>my_schedule<<<\n"); /* schedule */ next = my_current_task->next; prev = my_current_task; if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */ { my_current_task = next; printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid); /* switch to next process */ asm volatile( "pushl %%ebp\n\t" /* save ebp */ "movl %%esp,%0\n\t" /* save esp */ "movl %2,%%esp\n\t" /* restore esp */ "movl $1f,%1\n\t" /* save eip */ "pushl %3\n\t" "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) ); } return; }

通过my_time_handler()函数定时地不断向cpu发出中断,从而实现了时间片轮转。每调用1000次,就去将全局变量my_need_sched的值修改为1,通知正在执行的进程执行调度程序my_schedule。从而在my_schedule函数中完成进程的不断切换。

 

四、总结

(1)进程和中断在操作系统是是非常重要的两个部分,需要熟练掌握。
(2)EIP寄存器储存着当前执行的代码,可以通过更改EIP寄存器的值来更改当前执行的代码,从而实现进程切换。出于安全考虑,EIP寄存器的值不能被直接改变,但可以通过压栈+ret指令来间接改变。
(3)进程在执行过程中,当时间片用完之后需要进程切换时,需要保存当前的执行上下文环境,下次被调度的时候,需要回复进程的上下文环境。

转载于:https://www.cnblogs.com/xiguas/p/10519273.html

你可能感兴趣的文章
Python学习开始
查看>>
Android应用程序消息处理机制(Looper、Handler)分析(4)
查看>>
C++ 类成员的构造和析构顺序
查看>>
将String转化成Stream,将Stream转换成String
查看>>
java路径Java开发中获得非Web项目的当前项目路径
查看>>
Google API设计指南-资源名称
查看>>
最全React技术栈技术资料汇总(收藏)
查看>>
【工具使用系列】关于 MATLAB 遗传算法与直接搜索工具箱,你需要知道的事
查看>>
flex 学习笔记 stage
查看>>
Kali-linux Arpspoof工具
查看>>
java中三个类别加载器的关系以及各自加载的类的范围
查看>>
PDF文档页面如何重新排版?
查看>>
基于http协议使用protobuf进行前后端交互
查看>>
python3 + Django + uwsgi + nginx 配置部署笔记
查看>>
UML设计一个电影票务销售系统(四)
查看>>
如何给VEEAM 7 分配角色权限
查看>>
AlphaGo Zero用它来调参?【高斯过程】到底有何过人之处?
查看>>
《Redis官方教程》Redis集群规范(二)
查看>>
卸载金蝶kis记账王的方法
查看>>
centos中系统启动故障排除
查看>>