zoukankan      html  css  js  c++  java
  • 《linux内核分析》第二次课 实验作业

    潘聪  原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

    这次的实验主要是研究线程调度中的主动调度。

    ---------------------------------------------

    一、基础结构

    (1)进程:在mypcb.h中,进程由ip(eip)和sp(esp)共同组成。

    (2)进程控制块(PCB):进程号pid,状态(错误/运行中/停止运行),进程堆栈(包括内核栈和用户栈,此处合二为一了,详见[1]),进程,任务入口,通过next指针组成一个链表。

    二、初始化(__init my_start_kernel)

    生成零号进程:进程号0,状态运行,任务入口和ip为my_process的地址(此处将函数名作为指针使用,返回函数地址),sp设置为栈顶,链表next指向自身。

    生成其他进程:进程号依次分配,入口与零号进程相同,状态为未运行,sp设置为各自的栈顶(每个进程维护一个自身的栈),使链表连成环状链表。

    当前任务设定为零号进程。

    asm代码段:

     1     asm volatile
     2     (
     3         "movl %1, %%esp
    	" //set task[pid].thread.sp to esp
     4         "pushl %1
    	" //push ebp
     5         "pushl %0
    	" //push task[pid].thread.ip
     6         "ret
    	" //pop task[pid].thread.ip to eip
     7         "popl %%ebp
    	"
     8         :
     9         : "c" (task[pid].thread.ip), "d" (task[pid].thread.sp)
    10     );

    将零号进程的栈顶指针esp赋值给系统的esp,并将esp压栈(可以理解为ebp压栈),并将零号进程的ip压栈,并使用ret指令从该ip开始执行指令。

    理论上,如果这些进程不退出的话,最后一行popl永远不会被执行。

    三、主进程方法(my_process)

    每个指令周期进行一次循环,每10000000此循环后打印当前运行进程的进程号两次;若进程调度标识为1,在两次打印期间执行调度函数。

    四、调度句柄(my_timer_handler)

    每次中断后开始运行该函数,累积1000次中断后将调度标识置为1,从而使主进程方法运行调度函数。

    五、调度函数(my_schedule)

    定义两个tPCB类型的指针,分别指向当前进程和下一个进程。针对下个进程的运行状态不同(运行中或其他)分为两段汇编代码进行对应的进程上下文切换。

    1)下个进程正在执行:

     1 asm volatile
     2                 (
     3                         "pushl %%ebp
    	" //save ebp
     4                         "movl %%esp, %0
    	" //save esp
     5                         "movl %2, %%esp
    	" //restore esp
     6                         "movl $1f, %1
    	" // save eip |1f mean label 1
     7                         "pushl %3
    	"
     8                         "ret
    	" //restore eip
     9                         "1:	" //next process start here
    10                         "popl %%ebp
    	"
    11                         : "=m" (prev->thread.sp), "=m" (prev->thread.ip)
    12                         : "m"(next->thread.sp), "m" (next->thread.ip)
    13                 );

    将ebp压栈,当前进程的sp记录esp,当前进程的ip记录label1的地址,当进程切换返回后将栈中原ebp的内容重新弹回到ebp中。

    除此之外,还将当前进程设为下一进程,并打印切换文字。

    2)下个进程未执行:

    在执行汇编命令之前,先将下一进程状态设置为运行中,并将其设为当前进程。

    执行的汇编代码与1)类似,在此不进行赘述。

     ------------------------------------------------------------------------------

    最后,make后使用命令qemu -kernel arch/x86/boot/bzImage,生成图见下图:

    --------------------------------------------

    [1]从迷你型linux内核理解进度调度的原理http://itdreamerchen.com/%E4%BB%8E%E8%BF%B7%E4%BD%A0%E5%9E%8Blinux%E5%86%85%E6%A0%B8%E7%90%86%E8%A7%A3%E8%BF%9B%E7%A8%8B%E8%B0%83%E5%BA%A6%E7%9A%84%E5%8E%9F%E7%90%86/ 

  • 相关阅读:
    VS2005编译mysql5.1.68
    用boost库实现traceroute小工具
    linux内核选项部分翻译
    linux 内核中的锁机制RCU
    先装windows 还是linux ?
    U盘装ubuntu
    编译linux内核3.0
    root密码丢失了怎么办?
    linux配置文件
    新一代linux文件系统btrfs
  • 原文地址:https://www.cnblogs.com/codingpenguin/p/4340590.html
Copyright © 2011-2022 走看看