mykernel实验指导(操作系统是如何工作的)

实验要求

运行并分析一个精简的操作系统内核,理解操作系统是如何工作的

使用实验楼的虚拟机打开shell

  1. cd LinuxKernel/linux-3.9.4
  2. qemu -kernel arch/x86/boot/bzImage

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

实验截图

首先是

然后是

之后是

要建立一个简单的时间片轮转多道程序,按照实验楼给的链接,找到了几个源代码,如图

然后按这些修改文件,并加入文件mypcb.h

再运行,0,1,2,3,之间的进程切换

分析进程的启动和进程的切换机制

mypcb.h:

#define MAX_TASK_NUM 4  //定义总有4个任务/进程

#define KERNEL_STACK_SIZE 1024*8    //每个进程的堆栈大小为8KB

/*用于保有存当前进程的esp和eip*/

struct Thread {

unsigned long ip; //eip

unsigned long sp; //esp

};

/*定义进程结构体*/

typedef struct PCB {

int pid;//进程ID

volatile long state; //进程状态

char stack[KERNEL_STACK_SIZE];//进程堆栈

struct Thread thread;//保存esp、eip

unsigned long task_entry;//f进程入口

struct PCB * next;//在进程链表中指向下一个进程

struct PCB * prev;//在进程链表中指向上一个进程

}tPCB;

/*声明调度函数*/

void my_schedule(void);

mymain.c:

#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 = 0;

/*初始化0号进程*/

task[pid].pid = pid;

task[pid].state = 0;

/*进程入口指向进程处理函数*/

task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;

/*指向进程栈进址*/

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

/*进程链表中,next指向指向自己*/

task[pid].next = &task[pid];

/*创建其他进程*/

for(i=1; i< MAX_TASK_NUM; i++)

{

/*把0号进程的状态拷贝给当前进程,不同成员值再单独赋值*/

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

}

/* 运行0号进程*/

pid = 0;

/*把0号进程的地址赋给当前进程指针*/

my_current_task = &task[pid];

/*嵌入式汇编中%0,%1,%2,%3表示下面的参数,编号从0开始*/

asm volatile(

"movl %1, %%esp\n\t" /*把当前进程的栈指针赋给esp*/

"pushl %1\n\t"/*把当前进程的栈指保存到栈中*/

"pushl %0\n\t"/*保存当前进程的eip到栈中*/

"ret\n\t"/*返回操作*/

"popl %%ebp\n\t"/*弹出栈顶内容赋给ebp*/

:

: "c" (task[pid].thread.ip), "d" (task[pid].thread.sp)/*ecx=当前进程的eip, edx=当前进程的栈指针*/

);

//到此为止,0号进程就启动起来了

//end

}

void  my_process(void)

{

int i=0;

while(1)

{

i++;

if(i%100 == 0) {

printk(KERN_NOTICE "this is process %d- \n", my_current_task->pid);

/*判断是否需要切换进程,1需要切换,0不需要切换*/

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

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

/*

* 定时器中断处理函数

*/

void my_timer_handler(void)

{

/*判断是否需要切换进程*/

if(time_count % 100 == 0 && my_need_sched != 1) {

printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");

/*将进程切换标记为需要切换*/

my_need_sched = 1;

}

/* 计数器自加 */

time_count ++;

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

next = my_current_task->next;

prev = my_current_task;

//state:-1表示不可用,0表示正在执行,>0表示没有运行

if(next->state == 0) {

/*切换进程*/

asm volatile (

"pushl %%ebp\n\t" /*保存当前进程的ebp*/

"movl %%esp, %0\n\t" /*保存当前的栈指针到上一个进程的sp中*/

"movl %2, %%esp\n\t" /*把下一个进程的sp赋给esp*/

"movl $1f, %1\n\t" /*保存当前进程的eip到上进一个进程的ip中*/

"pushl %3\n\t" /*将下一个进程的ip压到栈中*/

"ret\n\t"/*返回*/

"1:\t"

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

asm volatile (

"pushl %%ebp\n\t"

"movl %%esp, %0\n\t"

"movl %2, %%esp\n\t"

"movl %2, %%ebp\n\t"

"movl $1f, %1\n\t"

"pushl %3\n\t"

"ret\n\t"

"popl %%ebp\n\t"

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

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

);

}

}

 

总结部分

对“操作系统是如何工作的”理解:

首先要了解计算机工作的三个法宝:

1.存储程序计算机

所有计算机的基础性的逻辑框架。

2.函数调用堆栈

在低级语言中并不很重要,但是堆栈技术是高级语言可以运行的基础。

3.中断机制

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

然后我们知道:操作系统是一管理电脑硬件与软件资源的程序,同时也是计算机系统的内核与基石。操作系统身负诸如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。操作系统是管理计算机系统的全部硬件资源包括软件资源及数据资源;控制程序运行;改善人机界面;为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,为用户提供方便的、有效的、友善的服务界面。(源自百度)

操作系统是一个庞大的管理控制程序,大致包括5个方面的管理功能:进程与处理机管理、作业管理、存储管理、设备管理、文件管理。

最终可知:操作系统保存了一些队列,每个队列都是一组等待某些资源的进程。资源在操作系统中得以合理的分配以及调度,用于解决处理这些进程。

注:

姓名:林涵锦

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

Linux内核分析— —操作系统是如何工作的(20135213林涵锦)的更多相关文章

  1. Linux内核分析——操作系统是如何工作的

    万子惠 + 原创作品转载请注明出处 + <Linux内核分析> 实验部分 使用实验楼的虚拟机打开shell 然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain. ...

  2. linux内核分析--操作系统是如何工作的?

    一个简单的时间片轮转多道程序 操作系统的"两把剑":中断上下文(保存现场和恢复现场)和进程上下文的切换 源代码的分析 *使用的源代码为视频中所使用的精简内核的源代码 首先分析myp ...

  3. Linux内核分析--操作系统是如何工作的

    “平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 一.初 ...

  4. 20135239益西拉姆 Linux内核分析 操作系统是怎样工作的?

    益西拉姆+ 原创作品+ <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 堆栈 堆栈是C语言程序运行时 ...

  5. LInux内核分析——计算机是如何工作的进行

    万子惠 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 " 实 ...

  6. linux内核分析--计算机是如何工作的

    实验部分 使用gcc -S -o main.s main.c -m32命令将源代码编译成汇编代码. 源代码如下: int g(int x) { return x + 9; } int f(int x) ...

  7. Linux内核分析— —计算机是如何工作的(20135213林涵锦)

    实验部分 (以下命令为实验楼64位Linux虚拟机环境下适用,32位Linux环境可能会稍有不同) 使用 gcc –S –o main.s main.c -m32 命令编译成汇编代码, int g(i ...

  8. Linux内核分析——计算机是如何工作的

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

  9. Linux内核分析— —构造一个简单的Linux系统MenuOS(20135213林涵锦)

    Linux内核分析— —构造一个简单的Linux系统MenuOS 实验内容 Linux内核的启动过程,从start_kernel到init进程启动 使用实验楼的虚拟机打开shell cd LinuxK ...

随机推荐

  1. SAP CRM 自定义控制器与数据绑定

    当用户从视图离开时,视图将失去它的数据.解决这个问题,需要引入自定义控制器(Custom Controller)(译者注:SAP CRM自定义端中,不同地方的Custom Controller会翻译为 ...

  2. 紧急整理了 20 道 Spring Boot 面试题,我经常拿来面试别人!

    面试了一些人,简历上都说自己熟悉 Spring Boot, 或者说正在学习 Spring Boot,一问他们时,都只停留在简单的使用阶段,很多东西都不清楚,也让我对面试者大失所望. 下面,我给大家总结 ...

  3. C#异步编程の-------异步编程模型(APM)

    术语解释: APM               异步编程模型, Asynchronous Programming Model EAP                基于事件的异步编程模式, Event ...

  4. 0 vs工程添加sdk

    配置64位 库目录:(VC++目录) 可选配置 VS SDK(如果报错缺少kernel32.lib) C:\Program Files (x86)\Microsoft SDKs\Windows\v7. ...

  5. 深入springboot原理——动手封装一个starter

    从上一篇文章<深入springboot原理——一步步分析springboot启动机制(starter机制)> 我们已经知道springboot的起步依赖与自动配置的机制.spring-bo ...

  6. ls操作总结

    la = ls -a ll = ls -l ls -lsh: ls -lsh train_log 看train_log的软链接的原始路径

  7. spring+springmvc+hibernate整合实例

    最近要弄一个自动化生成表及其实体对应的增删改查的框架,于是我想到了hibernate,hibernate就有根据实体自动建表,而且增删改查,都不需要想mybatis那样在xml文件中配置. 不过怎样让 ...

  8. PAT A1012 The Best Rank (25 分)——多次排序,排名

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  9. 【Codeforces 1120C】Compress String

    Codeforces 1120 C 题意:给一个串\(S\),将这个串分成\(t_1..t_m\),如果\(t_i\)在\(t_1..t_{i-1}\)中作为子串出现过,那么这个的代价是\(b\),否 ...

  10. highcharts中数据列点击事件

    Highcharts.chart('container', { xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul ...