1.三个法宝

①存储程序计算机工作模型,计算机系统最最基础性的逻辑结构;

②函数调用堆栈,堆栈完成了计算机的基本功能:函数的参数传递机制和局部变量存取 ;

③中断,多道程序操作系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其他程序。

2.堆栈的基本功能:

(1)函数调用框架、传递参数(32位)、保存返回地址(如eax保存返回值/内存地址)、提供局部变量空间

(2)与堆栈相关的寄存器:esp和ebp

与堆栈相关的操作:push(入栈时esp指针会减4)、pop(出栈时esp指针会加4)

(3)CS:eip总是指向下一条指令的地址

C代码中嵌入汇编代码

一、实验要求

完成一个简单的时间片轮转多道程序内核代码,代码见视频中或从mykernel找。

详细分析该精简内核的源代码并给出实验截图,撰写一篇署名博客,并在博客文章中注明“真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”,博客内容的具体要求如下:

题目自拟,内容围绕操作系统是如何工作的进行;

博客中需要使用实验截图

博客内容中需要仔细分析进程的启动和进程的切换机制

总结部分需要阐明自己对“操作系统是如何工作的”理解。

二、实验过程

首先通过cd LinuxKernel/Linux-3.9.4,“cd”表示进入目录Linux-3.9.4,用rm -rf mykernel命令强力删除mykernel。使用命令patch -pl< ../mykernel_for_linux3.9.4sc.patch,patch命令用于为特定软件包打补丁,该命令使用diff命令对源文件进行操作。格式:patch [选项] [原始文件 [补丁文件]

在Linux系统中,专门提供了一个make命令来自动维护目标文件,与手工编译和连接相比,make命令的优点在于他只更新修改过的文件(在Linux中,一个文件被创建或更新后有一个最后修改时间,make命令就是通过这个最后修改时间来判断此文件是否被修改),(make还是不太懂)使用命令qemu -kernel arch/x86/boot/bzImage搭建目标环境





通过cd mykernel ,打开mykernel目录,用ls命令看到目录内容中包括 mymain.c ,myinterrupt.c,使用命令vi mymain.c以及vi myinterrupt.c可以看到代码

可以看到每当i增加100000会执行(printf函数输出my_ start_ kernel _ here …)时会触发一次时钟中断,在由时钟中断处理函数输出(>..>>my_timer_handler<<…<)

二 操作系统内核源代码分析

首先是mypcb.h

+#define MAX_TASK_NUM 10 // max num of task in system //进程参与内核时间片转,这个系统最多有10个进程

+#define KERNEL_STACK_SIZE 10248 //每个进程栈的大小

+#define PRIORITY_MAX 30 //priority range from 0 to 30

+

+/
CPU-specific state of this task */

+struct Thread {

  • unsigned long ip;//point to cpu run address //用于eip的保存
  • unsigned long sp;//point to the thread stack's top address //用于esp的保存
  • //todo add other attrubte of system thread

    +};

    +//PCB Struct

    +typedef struct PCB{ //用于表示一个进程,定义了进程管理相关的数据结构
  • int pid; // pcb id //进程编号
  • volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
  • char stack[KERNEL_STACK_SIZE];// each pcb stack size is 1024*8
  • /* CPU-specific state of this task */
  • struct Thread thread;
  • unsigned long task_entry;//the task execute entry memory address ////进程第一次执行开始的地方
  • struct PCB *next;//pcb is a circular linked list //用于构造进程链表
  • unsigned long priority;// task priority
  • //todo add other attrubte of process control block

    +}tPCB;

+//void my_schedule(int pid);

+void my_schedule(void); //调用了my_schedule

接下来是mymain.c

+tPCB task[MAX_TASK_NUM];

+tPCB * my_current_task = NULL;

+volatile int my_need_sched = 0; //定义一个标志,用来判断是否需要调度

+

+void my_process(void);

+unsigned long get_rand(int );

+

+void sand_priority(void)

+{

  • int i;
  • for(i=0;i<MAX_TASK_NUM;i++)
  •   task[i].priority=get_rand(PRIORITY_MAX);

+}

+void __init my_start_kernel(void)

+{

  • int pid = 0; ////初始化一个进程0
  • /* Initialize process 0*/
  • task[pid].pid = pid;
  • task[pid].state = 0;/* -1 unrunnable, 0 runnable, >0 stopped */
  • // set task 0 execute entry address to my_process
  • 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(pid=1;pid<MAX_TASK_NUM;pid++)
  • {
  •    memcpy(&task[pid],&task[0],sizeof(tPCB));
  •    task[pid].pid = pid;
  •    task[pid].state = -1;
  •    task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1];
  • task[pid].priority=get_rand(PRIORITY_MAX);//each time all tasks get a random priority //每个进程都有自己的堆栈,把创建好的新进程放到进程列表的尾部
  • }
  • task[MAX_TASK_NUM-1].next=&task[0];
  • printk(KERN_NOTICE "\n\n\n\n\n\n system begin :>>>process 0 running!!!<<<\n\n");
  • /* 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 */
  • "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) //定义所有进程的工作,if语句表示循环1000万次才有机会判断是否需要调度。

+{

  • int i = 0;
  • while(1)
  • {
  •    i++;
  •    if(i%10000000 == 0)
  •    {
  •        if(my_need_sched == 1)
  •        {
  •            my_need_sched = 0;
  •   sand_priority();
  •  	my_schedule();
  •  }
  •    }
  • }

    +}//end of my_process

+//produce a random priority to a task

+unsigned long get_rand(max)

+{

  • unsigned long a;
  • unsigned long umax;
  • umax=(unsigned long)max;
  • get_random_bytes(&a, sizeof(unsigned long ));
  • a=(a+umax)%umax;
  • return a;

    +}

Linux第三周作业的更多相关文章

  1. 2018-2019-1 20189221《Linux内核原理与分析》第三周作业

    2018-2019-1 20189221<Linux内核原理与分析>第三周作业 实验二 完成一个简单的时间片轮转多道程序内核代码 实验过程 在实验楼中编译内核 编写mymain.c函数和m ...

  2. 2017-2018-1 20179205《Linux内核原理与设计》第三周作业

    <Linux内核原理与分析>第三周作业 教材学习总结 第三章 进程管理 进程是Unix操作系统抽象概念中最基本的一种,是正在执行的程序代码的实时结果:线程,是在进程中活动的对象.而Linu ...

  3. 2019-2020-1 20199329《Linux内核原理与分析》第三周作业

    <Linux内核原理与分析>第三周作业 一.上周问题总结: 第二周头脑风暴完成较慢 虚拟机libc配置错误 书本知识使用不够熟练 二.本周学习内容: 1.实验楼环境虚拟一个x86的CPU硬 ...

  4. 2017-2018-2 1723《程序设计与数据结构》第三周作业 & 实验一 总结

    作业地址 第三周作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1667 提交情况如图: 实验一:https://edu.c ...

  5. JAVA第三周作业(从键盘输入若干数求和)

    JAVA第三周作业(从键盘输入若干数求和) 在新的一周,我学习了JAVA的IO编程.下面的代码实现了从键盘输入若干数求和的目标.import java.util.Scanner; public cla ...

  6. 第三周作业、实时操作系统µC/OS介绍及其它内容

    作业要求 见<实时控制软件设计>第三周作业 1 阅读笔记--µC/OS 1.1 基本介绍 µC/OS是由Micrium公司研发的实时操作系统,以µC/OS-II或µC/OS-III为内核, ...

  7. 第三周作业(一)VS安装及单元测试练习

    第三周作业(一) 需求:练习教科书第22~25页单元测试练习,要求自行安装Visual Studio开发平台,版本至少在2010以上,要求把程序安装过程和练习过程写到博客上,越详细越好,要图文并茂,没 ...

  8. 2017-2018-1 JaWorld 第三周作业

    2017-2018-1 JaWorld 第三周作业 团队展示 队员学号 队名 团队项目描述 队员风采 团队的特色 团队合照 团队初步合作 前两周的反思与总结 需要改进的地方 团队选题 *采访老师或有开 ...

  9. 2017-2018-1 JAVA实验站 第三周作业

    2017-2018-1 JAVA实验站 第三周作业 团队展示 队名 JAVA实验站 拟作的团队项目描述 (2048)增加其他模式,使得2048更加丰富多彩 团队的首次合照 团队的特色描述 团队内部很团 ...

随机推荐

  1. django 配置 Django

    Django项目的设置文件位于项目同名目录下,名叫settings.py.这个模块,集合了整个项目方方面面的设置属性,是项目启动和提供服务的根本保证. 一.简述 settings.py文件本质上是一个 ...

  2. BMP操作_测试

    1.参考网址: http://blog.sina.com.cn/s/blog_678b377a0100mlyb.html http://blog.csdn.net/weiyongtao87/artic ...

  3. 构造函数中用:base

    如果person中有自己写的构造函数 则Student类的构造方法必须要加:base继承这个构造方法!因为默认的Student:base(空)构造方法已经被干掉了 构造方法的调用//base里的参数, ...

  4. top 命令常用操作

    1.显示进程参数 top -c 下面操作为top命令后操作 2.按cpu/mem排序 shift + p/m 3.高亮 排序列 按x键 4.高亮 变化进程行 按b键 5.显示cpu每核的运行状态 按1 ...

  5. Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...

  6. 01-python基础知识

    1.这两个参数是什么意思:*args,**kwargs?我们为什么要使用它们? 答案 如果我们不确定要往函数中传入多少个参数,或者我们想往函数中以列表和元组的形式传参数时,那就使要用*args:如果我 ...

  7. MySQL根据when-else条件批量更新

    #类型 0:默认 1:黑(0302) 2:白(0110) SELECT * FROM t_power_plat WHERE plat_type=1; UPDATE t_power_plat SET p ...

  8. 获取解码字符串指定位置的数值 Decoded String at Index

    2018-10-04 12:53:06 问题描述: 问题求解: 首先本题给出了问题的规模,从Note中我们可以看到解码后的字符串长度甚至可以达到2^63的长度,这个长度已经远远超过整型数的范围,因此如 ...

  9. 滑动拼图 Sliding Puzzle

    2018-09-09 22:01:02 问题描述: 问题求解: 问题很Interesting,其实本质就是解空间遍历,使用BFS就可以很快的予以解决~ public int slidingPuzzle ...

  10. php爬虫最最最最简单教程

    php爬虫最最最最简单教程 一.总结 一句话总结:用的爬虫框架,却是用的自己的例子(因为网站结构的变化,作者的例子不一定好用) 爬虫框架 自己例子 1.发现自己的运行效果和作者的不一样怎么办? 耐下性 ...