zoukankan      html  css  js  c++  java
  • 操作系统是如何工作的

    知识点:

    三个法宝:

    存储程序计算机、函数调用堆栈、中断机制。

    堆栈:

    堆栈机制是高级语言的起点。

    堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间。(函数调用框架、传递参数、保存返回地址、提供局部变量空间等等) 

    esp总指向栈顶,ebp总指向当前函数基址,eip总指向下一条指令地址。 

    堆栈操作在上一节已做说明,不再赘述。

     内嵌汇编语法:

    asm("statement" : output_regs: input_regs: clobbered_regs);

    加volatile表示不要优化代码。

    mykernel实验:

    使用实验楼的虚拟机打开shell

    cd LinuxKernel/linux-3.9.4
    qemu -kernel arch/x86/boot/bzImage
    

    然后cd mykernel 您可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c

    代码非常简单就是正常运行时打印上面,中断时打印下面。

    下面是一个简单的时间片轮转多道程序内核代码。

     mypcb.h


    #define MAX_TASK_NUM 4

    #define KERNEL_STACK_SIZE 1024*8

    /* CPU-specific state of this task */

    struct Thread {

    unsigned long ip;

    unsigned long sp;

    };

    typedef struct PCB{

    int pid;

    volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */

    char stack[KERNEL_STACK_SIZE];
    /* CPU-specific state of this task */

    struct Thread thread;

    unsigned long task_entry;

    struct PCB *next;

    }tPCB;

    void my_schedule(void);

     定义一个进程控制块pcb结构体

    task_entry:进程入口函数

    thread:保存eip和esp

    state:进程状态,用于判断是否调度

    mymain.c

    代码过长不再列出,主要功能是让程序从0号进程开始运行。

    下面这段代码是核心。

    asm volatile(

    //%0表示参数thread.ip,%1表示参数thread.sp。

    "movl %1,%%esp "     /* set task[pid].thread.sp to esp 把参数thread.sp放到esp中*/

    "pushl %1 "    /* push ebp 由于当前栈是空的,esp与ebp指向相同,所以等价于push ebp*/

    "pushl %0 "     /* push task[pid].thread.ip */

    "ret "     /* pop task[pid].thread.ip to eip */

    "popl %%ebp "

    :

    : "c" (task[pid].thread.ip),"d" (task[pid].thread.sp)     /* input c or d mean %ecx/%edx*/

    ); 

    myinterrupt.c

    主要功能是用于时钟中断处理和进程调度算法。

    同样注意这样一段代码。

    asm volatile(

    "pushl %%ebp " /* save ebp 保存当前进程的ebp*/

    "movl %%esp,%0 " /* save esp 把当前进程的esp赋给%0(指的是thread.sp),即保存当前进程的esp*/

    "movl %2,%%esp " /* restore esp 把%2(指下一个进程的sp)放入esp中*/

    "movl $1f,%1 " /* save eip $1f是接下来的标号“1:”的位置,把eip保存下来*/

    "pushl %3 " /*把下一个进程eip压栈*/

    "ret " /* restore eip 下一个进程开始执行*/

    "1: " /* next process start here */

    "popl %%ebp "

    : "=m" (prev->thread.sp),"=m" (prev->thread.ip)

    : "m" (next->thread.sp),"m" (next->thread.ip)

    );

    操作系统是如何工作的?

    操作系统通过存储程序计算机机制依次执行程序的指令,堆栈为程序运行时录调用路径和参数提供空间,中断用于异常处理和进程调度。

  • 相关阅读:
    Spark SQL saveMode 方式
    Spark SQL 读取json 里面的数据 ,jason 是 结构的数据
    SPark SQL 从 DB 读取数据方法和方式 scala
    SPark SQL 从 DB 读取数据方法和方式
    spark parquet 从hdfs 上读 和写 scala 版本
    spark parquet 从hdfs 上读 和写
    Spark streaming 采用直接读kafka 方法获取数据
    Topbeat --Metricbeat 在Windows上设置 centos kafka 打数据 成功
    php代码加入frameset后框架不显示
    【TP5笔记】TinkPHP5中引入资源文件
  • 原文地址:https://www.cnblogs.com/huyufeng/p/5232494.html
Copyright © 2011-2022 走看看