Linux内核分析— —操作系统是如何工作的(20135213林涵锦)
mykernel实验指导(操作系统是如何工作的)
实验要求
运行并分析一个精简的操作系统内核,理解操作系统是如何工作的
使用实验楼的虚拟机打开shell
- cd LinuxKernel/linux-3.9.4
- 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林涵锦)的更多相关文章
- Linux内核分析——操作系统是如何工作的
万子惠 + 原创作品转载请注明出处 + <Linux内核分析> 实验部分 使用实验楼的虚拟机打开shell 然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain. ...
- linux内核分析--操作系统是如何工作的?
一个简单的时间片轮转多道程序 操作系统的"两把剑":中断上下文(保存现场和恢复现场)和进程上下文的切换 源代码的分析 *使用的源代码为视频中所使用的精简内核的源代码 首先分析myp ...
- Linux内核分析--操作系统是如何工作的
“平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 一.初 ...
- 20135239益西拉姆 Linux内核分析 操作系统是怎样工作的?
益西拉姆+ 原创作品+ <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 堆栈 堆栈是C语言程序运行时 ...
- LInux内核分析——计算机是如何工作的进行
万子惠 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 " 实 ...
- linux内核分析--计算机是如何工作的
实验部分 使用gcc -S -o main.s main.c -m32命令将源代码编译成汇编代码. 源代码如下: int g(int x) { return x + 9; } int f(int x) ...
- Linux内核分析— —计算机是如何工作的(20135213林涵锦)
实验部分 (以下命令为实验楼64位Linux虚拟机环境下适用,32位Linux环境可能会稍有不同) 使用 gcc –S –o main.s main.c -m32 命令编译成汇编代码, int g(i ...
- Linux内核分析——计算机是如何工作的
马悦+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.计算机是如何工作的 ( ...
- Linux内核分析— —构造一个简单的Linux系统MenuOS(20135213林涵锦)
Linux内核分析— —构造一个简单的Linux系统MenuOS 实验内容 Linux内核的启动过程,从start_kernel到init进程启动 使用实验楼的虚拟机打开shell cd LinuxK ...
随机推荐
- 记一次ubuntuyu源码安装node.js
1.官网下载源码 2.下载后解压,在终端打开,并进入文件夹 3../configure 这一步可谓是一波三折,先是没有Python 安装Python 又说没有G++,安装G++后终于成功执行./con ...
- mysqld_safe启动服务器总结
mysqld_safe是服务端工具,用于启动mysqld,并且是mysqld的守护进程,mysqld_safe加&在后台运行$BASEDIR/bin/mysqld_safe & 优点就 ...
- Alpha冲刺! Day6 - 砍柴
Alpha冲刺! Day6 - 砍柴 今日已完成 晨瑶:讨论确定/解决了:网络判断使用广播方式.密集光点排布问题.丢失.db/记录html/多媒体文件的处理方式. 昭锡:Android工具包接口文档编 ...
- 捕获海康威视IPCamera图像,转成OpenCV能够处理的图像(二)
海康威视IPCamera图像捕获 捕获海康威视IPCamera图像.转成OpenCV能够处理的IplImage图像(一) 捕获海康威视IPCamera图像.转成OpenCV能够处理的IplImage图 ...
- margin auto 实现居中,与text-align:center的区别
本文导读:一个元素在水平方向上所占的长度,由width ,padding ,和margin 决定.这些值中,只有width和margin-left,margin-right可以设为auto,text- ...
- MySQL慢查询1- 开启慢查询
本文章摘自网络,学习之用 一.简介 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能. 二.参数说明 slow_query_log ...
- Qt 编程指南 7 添加背景
. #include "QT_Text1.h" #include <QtWidgets/QApplication> #include <QBitmap> i ...
- js之清除Cookie
最近新的系统开发用的是Cookie存储用户信息,使用des加密 工具类如下所示: /** * Copyright (c) 2013-Now http://jeesite.com All rights ...
- matlab padarray函数
1 padarray功能:填充图像或填充数组.用法:B = padarray(A,padsize,padval,direction) A为输入图像,B为填充后的图像, padsize给出了给 ...
- MATLAB:控制系统模型变换
1.多项式转换为零极点 [z,p,k]=tf2zp(num,den); 2.零极点转换为多项式 [num,den]=zp2tf(z,p,k); 3.状态空间转换成多项式传递函数 [num,den]=s ...