学号229 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/
Linux操作系统分析详细实验--时间片轮转多道程序
目录
1 实验简介
2 环境搭建以及运行mykernal
2.1 qemu简介:
2.2 安装qumu的环境及错误处理
2.3 下载kernal和补丁
2.4 编译程序及处理出现的问题
2.5 执行下载下来的Linux内核查看效果
2.6 查看相关代码
3 多进程时间片轮转实现
3.1 分析需要更改的文件
3.2 代码的分析和更改:mypcb.h的分析
3.3 mymain.c的分析更改
3.4 myinterrupt.c文件分析与更改
3.5 打开终端 重新编译 并再次查看效果
3.6 结果解读:
4 实验总结:
该实验是在孟老师提供的实验材料基础上完成,该实验主要实现了在自己的Ubuntu(16.04)上配置QEMU和linux(3.9.4).内核,并修改内核完成多线程的实现,下面是详细的实验过程。(参考孟老师给的资料:https://github.com/mengning/mykernel)
本实验是在自己的电脑中完成整个过程,转载请注明出处+ https://github.com/mengning/linuxkernel/ 谢谢。
Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。
安装时出现错误解决思路:
1。终端输入 ps aux ,列出进程。找到含有apt-get的进程,直接sudo kill PID。
2。强制解锁,命令
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock
再次进行安装即可以正常安装。
下面开始下载kernal3.9.4 并且下载补丁包并且打补丁。
make oldconfig和make config类似,但是它的作用是在现有的内核设置文件基础上建立一个新的设置文件,只会向用户提供有关新内核特性的问题,在新内核升级的过程 中,make oldconfig非常有用,用户将现有的配置文件.config复制到新内核的源码中,执行make oldconfig。
其中出现错误:
解决办法:
这个是因为系统版本太高,我使用的是ubuntu16.4。网上的解决办法是下载compiler-gcc5.h即可。暂时没有使用这种方法。而是直接在include/linux中找到compiler-gcc4.h重命名为compiler-gcc5.h编译。编译通过,没有问题出现继续实验。
继续进行编译提示编译成功。
下面开始在qemu中执行X86下的Linux程序,运行my_start_kernel。同时my_timer_handler时钟中断处理程序周期性执行。下面是程序的执行效果。
当前有一个CPU执行C代码的上下文环境,同时具有中断处理程序的上下文环境,现在已经初始化好了系统环境。
查看mykernal的代码
把mykernal的代码进行更改进行查看效果
经过分析,主要需要更改和查看以下文件。
首先,在mypcb.h中定义一个循环链表的结构体
线程的ip和sp用于切换时保存程序执行的上下文环境。
还在这里面定义pcb进程控制块
struct Thread thread; 定义了循环结构体。
下面应该在mymain中开始初始化一个关于PCB控制块的循环链表。
下面开始逐步扩充链表,在这里会循环你定义的最大的程序数MAX_TASK_NUM。
完成上面的程序,在mymain.c中的__init my_start_kernel函数就已经能够生成一个具有MAX_TASK_NUM个的PSB循环链表。
下面的示例代码是在该函数中实现的初始化堆栈esp、ebp、eip
创始化堆栈
movl %1, %%esp:将esp指向task[0]的堆栈stack顶端。然后将task[0].thread.sp即堆栈顶端地址压栈,为以后的%ebp的复位使用。将task[0].thread.ip即程序入口my_process压栈。将task[0].thread.ip即程序入口my_process放到eip。
继续解析mymain
在mymain中定义my_process 其循环执行因为my_need_sched初始为0,只用当时钟中断my_timer_handler将my_need_sched置为1时,才会调用my_schedule()。
该文件主要控制程序的中断 其中时间片轮转算法在my_schedule中定义
循环运行的代码:
最后的执行效果可以看到程序在四个进程之间一直在切换,
系统开始在process 0中运行,在出现my_timer_handler后中断 然后跳转到process 1,之后在process 1中运行,在出现my_timer_handler后跳转到process 2,之后在process 2中运行,在出现my_timer_handler后跳转到process 3,之后在process 3中运行,在出现my_timer_handler后跳转到process 0,依次循环。