• 从编写操作系统的角度看上下文切换


    0 上下文切换

    上下文切换(Context Switching)指的是切换处理器执行的任务时发生的一系列动作。

    感性地说,从一个任务切换到另一个任务,过一段时间后又想切换回来,必然是需要保存一些东西的,这些东西就是某个任务的上下文。

    因此,被要实现多任务的操作系统,或者简单的任务调度器,就肯定绕不过上下文切换。

    而要知道上下文切换到底需要做什么,可以想看看描述一个任务及其状态到底需要哪些参数。

    1 任务创建

    先看看任务创建需要的所有信息——地址寄存器、一些特殊寄存器和返回地址。而所谓的上下文(context,避免读着别扭后面一直用context代上下文),也在介绍中断时作了定义啦。

    对操作系统而言,创建任务等同于初始化用户提供的栈和入口地址(entry point)的上下文(context)。通常创建任务的函数都是没有返回值的。创建任务需要的参数包括入口地址、栈地址、栈大小和传给栈的参数。原型类似于下面这样。

    void add_task(taskFunc *entry, void *stack, unsigned int stack_size, void *arg);
    
    • 1

    这个函数拿到这些参数信息之后,需要做两件事情——初始化任务堆栈、向操作系统或者运行时(runtime)注册任务,也就是告知系统该任务的信息。

    2 注册任务

    一般说来,操作系统或者系统内核会用一个叫任务控制块(Task Control Block,TCB)的数据结构来保存任务的信息。

    对于简单的运行时系统而言,不需要保存详细的任务信息,只需要保存各任务堆栈的入口地址task_stacks[i]、已经注册的任务数量allocated_tasks,以及当前任务的标号current_task(也可以是别的,主要是用来标记处理器现在在执行的的哪一个任务,即task_stacks[current_task]。所以维护下面这几个全局变量就绰绰有余了。

    unsigned int *task_stacks[MAXTASKS];
    unsigned int allocated_tasks = 0;
    int current_task = -1;
    
    • 1
    • 2
    • 3

    3 初始化任务栈

    任务栈的初始化也是分两步走——第一步是计算任务栈栈顶(the top of the stack)地址,第二步是填充任务栈。

    略有奇怪哈,要得到任务栈栈顶地址的话,直接用任务栈地址+栈长度不就好啦,怎么感觉还需要别的操作,单独成一步?答案是栈顶地址有字节对齐需求。

    任务创建函数往往不会对堆栈地址和长度设置约束,但处理器可能需要堆栈的地址是 1632 或者 64 的倍数,这就需要咱在计算栈顶地址时做一点处理。

    sp = (unsigned int *)((int)(stack + stack_size) & 0xfffffff0);
    
    • 1

    像这样,把地址末尾不足 f 的值抹去,也就是对求和结果做一下向下取整,这样就能保证栈顶地址(sp)是16的倍数。

    这里又联想到内存管理。内存管理算法也会刻意对申请地空间大小做这样的向下取整操作,以减少内存中的小碎片。这样横向比较一下,也就能理解malloc函数返回实际分配的空间大小的意义了

    参考

    • Xtensa, programmers_guide.pdf, chapter 8 Context Switching
  • 相关阅读:
    零成本体验美国云服务器,更方便的体验和选择
    springmvc集成ehcache
    JSON & XML
    【物联网】常见电子元器件(电阻、电容、电感、二极管、三极管)综合,详细分析原理及其应用
    【C++项目】高并发内存池第四讲 申请内存过程介绍流程介绍
    根据pid查看jar包(windows)
    [23] T^3Bench: Benchmarking Current Progress in Text-to-3D Generation
    Effective Modern C++[实践]->只要函数不会发射异常,就为其加上noexcept
    Spring Security(八) —— 异常处理
    【Linux operation 44】Linux(red hat)查看看内核版本方法
  • 原文地址:https://blog.csdn.net/qq_33904382/article/details/126567896