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

张潇月+《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、实验

打开实验楼,在老师早就建立好的环境里运行并分析一个简单的操作系统内核。

首先是进入老师搭建的平台

然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c

以上是本次实验过程截图。

二、分析实验代码

Mymain.c

/*

* linux/mykernel/mymain.c

*

* Kernel internal my_start_kernel

*

* Copyright (C) 2013 Mengning

*

*/

#include <linux/types.h>

#include <linux/string.h>

#include <linux/ctype.h>

#include <linux/tty.h>

#include <linux/vmalloc.h>

#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;/* 0号进程*/

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<MAX_TASK_NUM;i++)

{

memcpy(&task[i],&task[0],sizeof(tPCB));

task[i].pid = i;

task[i].state = -1;

task[i].thread.sp = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-1];

task[i].next = task[i-1].next;

task[i-1].next = &task[i];

}

/* start process 0 by task[0] */

pid = 0;/*0号进程开始执行*/

my_current_task = &task[pid];

asm volatile(

"movl %1,%%esp\n\t" /*%1表示下面的参数sp*/

"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*/

);

}

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);

}

}

}

Myinterrupt.c

/*

* linux/mykernel/myinterrupt.c

*

* Kernel internal my_timer_handler

*

* Copyright (C) 2013 Mengning

*

*/

#include <linux/types.h>

#include <linux/string.h>

#include <linux/ctype.h>

#include <linux/tty.h>

#include <linux/vmalloc.h>

#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 */

{

/* 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)

);

my_current_task = next;

printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);

}

else

{

next->state = 0;

my_current_task = next;

printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);

/* switch to new process */

asm volatile(

"pushl %%ebp\n\t" /* save ebp */

"movl %%esp,%0\n\t" /* save esp */

"movl %2,%%esp\n\t" /* restore esp */

"movl %2,%%ebp\n\t" /* restore ebp */

"movl $1f,%1\n\t" /* save eip */

"pushl %3\n\t"

"ret\n\t" /* restore eip */

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

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

);

}

return;

}

Mypcb.c

/*

* linux/mykernel/mypcb.h

*

* Kernel internal PCB types

*

* Copyright (C) 2013 Mengning

*

*/

#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;    /*用thread来存储ip,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);

三、操作系统是怎么工作?

程序在经过编译链接后形成可执行程序。在加载到内存时,系统根据可执行程序初始化进程的地址空间。CPU根据ebp/eip寻址进程地址空间中的cs段的代码,取值,译码并依次执行,进行数据处理。在函数调用时,会先把参数压栈,接着执行call指令-压栈参数cs:eip并跳转到被调用函数的cs段,然后构造被调函数的堆栈,之后,同样的取值,译码并执行,进行数据处理。在被调用函数结尾,会恢复调用函数的cs段的指令。

Linux内核分析 第二周的更多相关文章

  1. linux内核分析第二周

    网易云课堂linux内核分析第二周 20135103                王海宁 <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  2. LINUX内核分析第二周学习总结——操作系统是如何工作的

    LINUX内核分析第二周学习总结——操作系统是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

  3. Linux内核分析第二周学习笔记

    linux内核分析第二周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  4. Linux内核分析第二周--操作系统是如何工作的

    Linux内核分析第二周--操作系统是如何工作的 李雪琦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

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

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

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

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

  7. Linux内核分析第二周学习总结:操作系统是如何工作的?

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈 ...

  8. Linux内核分析第二周:操作系统是如何工作的

    第一讲 函数调用堆栈 计算机是如何工作的? (总结)——三个法宝 1,存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: 2,函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆 ...

  9. linux内核分析 第二周 操作系统是如何工作的

    银雪纯 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.计算机是如何工作的 ...

随机推荐

  1. Python 各进制间的转换(转)

    转载自:http://blog.chinaunix.net/uid-21516619-id-1824975.html python 2.6以后内置函数#10进制转为2进制>>> bi ...

  2. 转载:python中的StringIO模块

    注意:python3中应使用io.StringIO StringIO经常被用来作为字符串的缓存,应为StringIO有个好处,他的有些接口和文件操作是一致的,也就是说用同样的代码,可以同时当成文件操作 ...

  3. Head First 设计模式之观察者模式(Observer Pattern)

    前言: 这一节开始学习观察者模式,开始讲之前会先像第一节那样通过一个应用场景来引入该模式.具体场景为:气象站提供了一个WeatherData对象,该对象可以追踪获取天气的温度.气压.湿度信息,Weat ...

  4. Python之import

    今天写了一个很简单的111.py文件(模块),用命令行直接import 111报错:syntaxerror:invalid systax 从网上查了一下,原因有如下集中: 1,所导入模块没有sys.p ...

  5. javascript判断某种元素是否进入可视区域

    判断是否在指定的可视区域内,先用最简单的方式,比如整个页面为可视区域 找到几个关键因素: sTop= $(window).scrollTop();  //滚动条距顶部的高度 clientHeight= ...

  6. 说说Web.Config与App.Config

    说到web.config和app.config大家都很熟悉,我们都叫他们配置文件,平时用的多,注意的少.两个有啥区别呢,很简单,一句话:如果是web程序,如webform项目类型和mvc项目类型就是w ...

  7. vue.js 2.0开发(4)

    使用vue-cli,首先安装: npm install -g vue-cli 安装完了执行vue命令,会出现 vue init <template-name> <project-na ...

  8. Windows 驱动程序工具包中的头文件

    MSDN原文:https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff554695(v=vs.85).aspx Windows 驱动程序 ...

  9. docker使用阿里云Docker镜像库加速

    官方镜像下载实在是慢,于是开通了阿里云开发者帐号, 官方帮助 阿里云Docker镜像库 阿里云容器Hub服务:http://dev.aliyun.com/search.html 来自云端的容器Hub服 ...

  10. linux配置ftp

    参考: http://www.cnblogs.com/acpp/archive/2010/02/08/1665876.html http://blog.csdn.net/huzhenwei/artic ...