linux系统分析第一次实验报告

学号:413

原创作品转载请注明出处 https://github.com/mengning/linuxkernel/
使用孟宁老师的github帐号中提供的Mykernel资源,在我的机器上进行了一个关于时间片轮转调度程序的实现。

实验环境:

     . VMware Workstation----->安装Ubuntu16.04虚拟机 . 安装Mykernel(基于Linux Kernel 3.9.4)

按照孟宁老师github帐号中提供的Mykenrnel安装步骤,在本机上进行编译安装。

步骤如下:

sudo apt-get install qemu # install QEMU
sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.9.4.tar.xz # download Linux Kernel 3.9.4 source code
wget https://raw.github.com/mengning/mykernel/master/mykernel_for_linux3.9.4sc.patch # download mykernel_for_linux3.9.4sc.patch
xz -d linux-3.9.4.tar.xz
tar -xvf linux-3.9.4.tar
cd linux-3.9.4
patch -p1 < ../mykernel_for_linux3.9.4sc.patch
make allnoconfig
make

编译过程中遇到的问题

由于gcc版本较高,在编译的过程中会遇到compiler-gcc5.h文件丢失。

解决办法:

 直接使用compiler-gcc4.h修改名称进行替换之后编译通过。

###下面是安装linux-3.9.4编译成功之后的截图


编译成功之后运行Mykernel当中的例子,运行结果如下:
对应mymain.c和intterupt.c两个文件,前者是用来循环输出my_start_kernel here语句,后者是用来记录被时钟中断时候的输出。

 参考孟宁老师的代码,在mymain.c和myinterupt.c文件中进行相关代码的修改。

在孟宁老师的github主页中下载主要的文件,下面是该项目的链接:
https://github.com/mengning/mykernel
其中使用到的有mymain.c和myinterrupt.ci以及mypcb.h。
在进行相关代码的修改之后,返回至linux-3.9.4目录下,进行重新编译,命令如下:

cd /your_path/linux-3.9.4/
make clean
make allnoconfig
make -j4

编译完成使用qemu -kernel arch/x86/boot/bzImage命令进行测试。

首先展示运行结果:



上图中展示的是从进程3切换到进程0,以及进程0切换至进程1。

对于几个主要文件进行分析:

mymain.c: 初始化各个进程并启动0号进程。
myinterrupt.c:时钟中断处理和进程调度算法。
mypcb.h : 进程控制块PCB结构体定义。

对于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;/* -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<MAX_TASK_NUM;i++){memcpy(&task[i],&task[0],sizeof(tPCB));task[i].pid = i;//*(&task[i].stack[KERNEL_STACK_SIZE-1] - 1) = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-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;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 */: : "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/);
} int i = 0;void my_process(void)
{    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);}     }
}

这里的函数 my_start_kernel 是系统启动后,最先调用的函数,在这个函数里完成了0号进程的初始化以及启动,并创建了进程PCB。在模拟系统里,每个进程的函数(my_process 函数)在执行的时候,会打印出当前进程的 id,从而使得我们能够看到当前正在执行的进程信息。其中的全局标志变量my_need_sched,其值为 1 时,就调用 my_schedule 完成对进程的调度。

对于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 1if(time_count%1000 == 0 && my_need_sched != 1){printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");my_need_sched = 1;} time_count ++ ;
#endifreturn;
}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_timer_handler 函数会被内核周期性的调用,每调用1000次,就将全局变量my_need_sched置1,写入my_schedule中,在my_schedule函数中,完成进程的切换。可以通过下一个进程的state知道该进程是否被调度。进程切换依然是通过内联汇编代码实现,无非是保存旧进程的eip和堆栈,将新进程的eip和堆栈的值存入对应的寄存器中。

最后是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  /* 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的结构体,用于存储当前进程中正在执行的线程的ip和sp的值
PCB结构体中的各个字段含义如下
pid:进程号

state:进程状态,在模拟系统中,所有进程控制块信息都会被创建出来,其初始化值就是-1,如果被调度运行起来,其值就会变成0

stack:进程使用的堆栈

thread:当前正在执行的线程信息

task_entry:进程入口函数

next:指向下一个PCB,mykernel中所有的PCB是以链表的形式组织起来的。

对于函数my_schedule,在my_interrupt.c文件叙述中已叙述过,在mymain.c中的各个进程函数会根据一个全局变量的状态来决定是否调用它,从而实现主动调度。

总结:

 通过该实验,了解了进程调度和中断机制,我们知道当分配个进程的时间用完后需要进程切换时,需要保存当前的执行上下文环境,在进程再次被调度时,以便返回该进程的上下文环境。再次感谢孟宁老师提供的资源。

Linux系统分析第一次实验报告相关推荐

  1. 第一次实验报告Hadoop

    第一次实验报告Hadoop(三种模式安装配置) 实验小结 通过对Hadoop模式安装配置的学习,我学习和熟悉了一些新的指令操作,对hadoop的基本操作有了基础的掌握,hadoop的环境配置原理和编译 ...

  2. linux内存管理实验malloc,linux内存管理实验报告.doc

    linux内存管理实验报告 操作系统实验报告 院别:XXXXXX 班级:XXXXXX 学号:XXXXXX 姓名:稻草人 实验题目:内存管理实验 实验目的 通过本次试验体会操作系统中内存的分配模式: 掌 ...

  3. Linux系统内存管理实验报告,linux内存管理实验报告

    <linux内存管理实验报告>由会员分享,可在线阅读,更多相关<linux内存管理实验报告(13页珍藏版)>请在人人文库网上搜索. 1.操作系统实验报告院别:XXXXXX班级: ...

  4. 西安交通大学计算机组成原理实验,西安交通大学计算机组成原理专题实验(上)第一次实验报告.pdf...

    西安交通大学计算机组成原理专题实验(上)第一次实验报告 计算机组成原理专题实验报告(第一次) 学生姓名 专业/班级 计算机11 班 学 号 所在学院 电信学院 指导教师 姜欣宁 提交日期 2013 年 ...

  5. 课程linux实验报告,Linux课程综合训练实验报告

    Linux课程综合训练实验报告 1) 实验目的: 熟练掌握Linux操作系统的使用,掌握Linux的各项系统管理功能,掌握Linux下各类网络服务的安装.配置以及使用,并能用shell脚本实现简单的管 ...

  6. 计算机组成原理中J1J3是什么,计算机组成原理第一次实验报告.doc

    计算机组成原理第一次实验报告 实验报告 专业班级 姓 名 机器号:学 号E-mail分步成绩实验表现实验报告总成绩 实验一 寄存器及数据输出实验 一.实验目的 1.掌握寄存器器件的工作原理,了解COP ...

  7. 西南科技大学数电FPGA第一次实验报告

    西南科技大学数电实验FPGA报告 #数字信号基本参数与逻辑门电路功能测试及FPGA 更多请加qq:2934915716## 标题 西南科技大学数电FPGA第一次实验 西南科技大学数电FPGA第一次实验 ...

  8. 计算机组成原理中J1J3是什么,计算机组成原理第一次实验报告

    <计算机组成原理第一次实验报告>由会员分享,可在线阅读,更多相关<计算机组成原理第一次实验报告(18页珍藏版)>请在人人文库网上搜索. 1.机器号_______________ ...

  9. 【全套完结】信号与线性系统分析--Matlab实验报告手册【建议保存】

    目录 一.熟悉MATLAB环境和基本信号的产生与运算 二.信号的变换 三.连续系统的时域分析 四.离散系统的时域分析 五.连续信号的频谱分析 六.连续信号的频域分析 七.连续信号的采样与恢复 八.拉普 ...

最新文章

  1. Java基础知识强化之IO流笔记03:throws的方式处理异常
  2. 计算机组成原理 陈泽,江西师范大学-计算机组成原理的期末复习.doc
  3. el-tree与el-transfer结合成树形穿梭框(tree-transfer)
  4. python3安装教程配置配置阿里云
  5. java开发工程师工作内容怎么写
  6. linux vps 运行exe文件夹,在centos环境下运行.exe文件
  7. 自适应好看的引导单页源码-无后台
  8. jquery-显示隐藏-链式调用
  9. kaggle实战—泰坦尼克(二、数据清洗及特征处理)
  10. python的try和except_关于python:修复try和except中的无效语法错误
  11. 小书童开源免费的二维码批量生成工具
  12. 刷题记录:牛客NC23803DongDong认亲戚
  13. Java开发面试必问项。标识符、字面值、变量、数据类型,该学了
  14. Vue+Element UI完成新建调查问卷
  15. word文档内容联动
  16. 链改升级,区块链——炳德区块链
  17. 基于WEB 的实时事件通知
  18. GRPC的四种数据流以及案例
  19. Git从入门到熟练第八讲 创建和使用分支
  20. RDKit|分子指纹提取、相似性比较及应用

热门文章

  1. 如何组建性能测试团队?
  2. 广州区块链系统or积分联盟
  3. OpenStack 入门体验
  4. html5 直接调用摄像头,HTML5调用摄像头并拍照
  5. 【深度学习之美】局部连接来减参,权值共享肩并肩(入门系列之十一)
  6. 从基金到股票,从股票到合约,从一夜暴富到一夜暴负的惨痛经历!
  7. U盘mp3移动硬盘“文件或目录损坏且无法读取”错误的修复
  8. 【SubPhaser-多倍体亚基因组分型流程解读】
  9. C语言16位定标,DSP定标方法
  10. 快捷方式‘*.lnk’指向的驱动器或网络连接不可用,笔记本读不到机械硬盘