zoukankan      html  css  js  c++  java
  • 2019-2020-1 20199318《Linux内核原理与分析》第三周作业

    第2章 操作系统是如何工作的

    一、学习笔记

    1. 计算机的三大法宝:存储程序计算、函数调用机制、中断。
    2. 堆栈的具体作用有:记录函数调用框架、传递函数参数、保存返回值的地址、提供函数内部局部变量的存储空间等。
    3. 堆栈相关的寄存器:
       ESP:堆栈指针(stack pointer)
       EBP:基址指针(base pointer),在C语言中用作记录当前函数调用基址。
    4. 对于X86体系结构来讲,堆栈空间是从高地址向低地址增长的,如图所示:
    

    5. 堆栈操作:
       push:栈顶地址减少4个字节(32位),并将操作数放入栈顶存储单元。
       pop:栈顶地址增加4个字节(32位),并将栈顶存储单元的内容放入操作数。
    6. 其它一些指令:
       顺序执行:总是指向地址连续的下一条指令。
       跳转/分支:执行这样的指令时,CS:EIP的值会根据程序需要被修改。
       call:将当前CS:EIP 的值压入栈顶,CS:EIP指向被调用函数的入口地址。
       ret:从栈顶弹出原来保存在这样的CS:EIP的值,放入CS:EIP中。
    

    二、试验记录

    1.进程初始化代码

    asm volatile(
        "movl %1,%%esp
    	"   //将进程原堆栈栈顶的地址(这里是初始化的值)存入ESP寄存器。
        "pushl %1
    	"        //将当前EBP寄存器值入栈。
        "pushl %0
    	"        //将当前进程的EIP(这里是初始化的值)入栈。
        "ret
    	"             //ret命令正好可以让入栈的进程EIP保存到EIP寄存器中。
        "popl %%ebp
    	"      //与前面push指令结对出现。
    

    2.进程0启动,开始执行my_process(void)函数的代码。

    if(next->state==0)//next->state==0对应进程next对应进程曾经执行过。
    {
        //进行进程调度关键代码。
        asm volatile(
            "pushl %%ebp
    	"   //保存当前EBP到堆栈中。
            "movl %%esp,%0
    	" //保存当前ESP到当前PCB中。
            "movl %2,%%esp
    	" //将next进程的堆栈栈顶的值存到ESP寄存器。
            "movl $1f,%1
    	"   //保存当前进程的EIP值,下次恢复进程后将在标号1开始执行。
            "pushl %3
    	"      //将next进程继续执行的代码位置(标号1)压栈。
            "ret
    	"           //出栈标号1到EIP寄存器。
            "1:	"              //标号1,即next进程开始执行的位置。
            "pop1 %%ebp
    	"    //恢复EBP寄存器的值。
            : "=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<<<
    ",prev->pid,next->pid);
    }
    else
    {
        next-state=0;
        my_current_task=next;
        printk(KERN_NOTICE ">>>switch %d to %d<<<
    ",prev->pid,next->pid);
    //转换到新的进程中
        asm volatile(
          "pushl %%ebp
    	"   //保存当前EBP到堆栈中。
          "movl %%esp,%0
    	" //保存当前ESP到当前PCB中。
          "movl %2,%%esp
    	" //载入next进程的栈顶地址到ESP寄存器。
          "movl %2,%%ebp
    	" //载入next进程的堆栈基地址到EBP寄存器
          "movl $1f,%1
    	"   //保存当前EIP寄存器值到PCB,这里$1f是指上面的标号1。
          "push %3
    	"       //把即将执行的进程的代码入口地址入栈。
          "ret
    	"           //出栈进程的代码入口地址到EIP寄存器。
          : "=m" (prev->thread.sp),"=m" (prev->thread.ip)
          : "m" (next->thread.sp),"m" (next->thread.ip)
        );
    }
    

    3.对上述代码的堆栈调用过程进行分析。

    为了分析简单,假设系统只有两个进程,分别是进程0和进程1.进程0由内核启动时初始化执行,然后需要进程调度,开始执行进程1。下面从进程1被调度开始分析堆栈变化,因为进程1从来没有被执行过,是第一次被调度执行,此时执行else中的代码。
    

    到这里开始执行进程1,如果进程1执行的过程中发生了进程调度,进程0重新被调度执行了,应该执行前述if中的代码,具体的堆栈变化与上图所示过程相似。
    

    总结

    本章内容最重要的是进程的切换,进程在执行过程中,当时间片用完需要进程切换时,需要先保存当前的进程执行的上下文环境,下次进程被调度时,需要恢复进程的上下文环境。这样实现多道程序的并发执行。
    

  • 相关阅读:
    HDU 5492 Find a path
    codeforce gym 100548H The Problem to Make You Happy
    Topcoder SRM 144 Lottery
    codeforce 165E Compatible Numbers
    codeforce gym 100307H Hack Protection
    区间DP总结
    UESTC 1321 柱爷的恋爱 (区间DP)
    HDU 4283 You Are the One (区间DP)
    HDU 2476 String painter (区间DP)
    UESTC 426 Food Delivery (区间DP)
  • 原文地址:https://www.cnblogs.com/SunMaolin/p/11604074.html
Copyright © 2011-2022 走看看