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. apriori推荐算法

    大数据时代开始流行推荐算法,所以作者写了一篇教程来介绍apriori推荐算法. 推荐算法大致分为: 基于物品和用户本身 基于关联规则 基于模型的推荐 基于物品和用户本身 基于物品和用户本身的,这种推荐 ...

  2. [ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.3.1:

    security-sdk-1.0.jar已经存在于D:/secServerSDK-test/src/main/resources/lib下 报错如下: xxxxxx@xxxxxxxx /d/secSe ...

  3. [Linux] - Docker制作nginx+php

    使用Docker制作nginx+php的镜像,这里的镜像是centos + nginx 1.9.7 + php 5.6.14 首先下载到nginx和php: nginx-1.9.5.tar.gz 下载 ...

  4. [2014.01.27]WFsoft.wfLibrary.wfIniFile 1.5

    完全支持.net 2.0编写,对下一代操作系统平稳过渡.     不使用[DllImport("kernel32")]的方式,完全自主的.net 2.0自主解析.    完整支持键 ...

  5. View加载过程

    1. 先判断子类是否重写了loadView,如果有直接调用.之后调viewDidLoad完成View的加载.2 .如果是外部通过调用initWithNibName:bundle指定nib文件名的话,V ...

  6. 在UIView上添加tableView设置代理属性

  7. jquery “做页面滚动到某屏时改变状态标题” 所用知识点记录

    浏览器滚动条滚动时触发事件 //浏览器滚动条滚动时触发事件 $(window).scroll(function(){}); 浏览器窗口大小改变时触发事件 //浏览器窗口大小改变时触发事件 $(wind ...

  8. udacity google deep learning 学习笔记

    1.为什么要在卷积网络中加入pooling(池化) 如果只利用卷积操作来减少feature map的大小,会失去很多信息.所以想到一种方法,减小卷积时的stride,留下大部分信息,通过池化来减小fe ...

  9. 检测文件是否有BOM 头,并删除BOM头(php)

    将下面文件放在网站根目录访问即可,它会遍历当前目录下所有子目录,检测文件是否含有BOM头,并删除BOM头 <?php //remove the utf-8 boms //by magicbug ...

  10. 锋利的jQuery学习总结

    通过对<锋利的jQuery>(第二版)一书的学习,发现此书讲解通俗易懂,是学习jQuery的一本很好的指导书,特作如下总结.此书主要讲解了jQuery的常用操作,包括认识jQuery,jQ ...