pa4学习笔记

多道程序(多任务处理)

  • 含义:
    • cpu一次载入多个程序
    • 先运行第一个程序
    • 当第一个程序在等待io操作时
    • 运行第二个程序
    • 以此类推…

上下文切换流程(yield-os为例)

  1. 操作系统-main函数
    1. 初始化,注册回调函数 schedule
    2. kontext 为两个进程分别创建上下文
      1. 进程的上下文以及指向它的指针cp的位置![[Pasted image 20240910204926.png|400]]

      2. 创建一个cp指向context

      3. 让context中的mecp为entry

      4. 让context中的gpr[10] (a0)为arg

      5. 返回值为cp

    3. 调用yield,调用ecall
  2. 硬件-nemu指令-ecall
    1. 存入当前上下文信息,跳转到mtvec(异常入口)am_asm_trap
    2. 将上下文信息存入当前进程的栈==(还没将地址存给cp)
    3. 将sp(栈指针)存入a0
    4. 调用__am_irq_handle,参数为a0
      1. 判断事件
      2. 将mepc+4 ==(下次回到这个进程就执行下一条指令)
    5. 调用回调函数 schedule
  3. 操作系统-schedule函数
    1. (current是栈顶指针,指向某个栈的顶部,用途是在多个进程的栈顶中切换,指示当前运行的进程)
    2. 存储当前进程的上下文地址到自己的栈中的cp中
    3. 将current指向新的栈顶
    4. 新栈顶的上下文地址cp返回
  4. 硬件-nemu trap.s
    1. 从__am_irq_handle返回 ,返回值为a0
    2. 将sp更新为a0(指向其他进程的栈的指针)
    3. (此时的上下文地址已经变成另外一个进程的上下文地址,所读取的上下文信息变成了另外一个进程的上下文信息)
    4. 恢复 mstatus 和 mepc 寄存器、通用寄存器(包括在kcontext中存的a0)(完成进程的切换)
    5. mret跳转到==(新进程的)mepc(entry)==继续执行 - f函数
  5. 操作系统-f函数
    1. 打印
    2. 等待
    3. 调用yield
    4. 重复2、3、4

RT-Thread

两个抽象层(这一思想和AM非常类似)

  • BSP(Board Support Package)
    • 为各种型号的板卡定义了一套公共的API
    • 并基于这套API实现RT-Thread内核;
    • 而对于一款板卡, 只需要实现相应的API, 就可以将RT-Thread内核运行在这款板卡上
    • 当然, BSP也不仅仅是针对真实的板卡, 也可以对应QEMU等模拟器, 毕竟RT-Thread内核无需关心底层是否是一个真实的板卡.
  • libcpu
    • 为各种CPU架构定义了一套公共的API
    • RT-Thread内核也会调用其中的某些API

需要实现的函数

  • rt_hw_stack_init()

    • stack_addr 需要地址对齐到sizeof(uintptr_t)
    • ![[Pasted image 20240911140935.png|500]]
    1. 调用kontext构造上图的栈
    2. entry为一个包裹函数
    3. 参数为parameter的首地址,
    4. 在包裹函数中解析parameter首地址
      1. 将tentry
      2. texit
      3. parateter解析出来
    5. 在包裹函数中调用tentry
    6. tentry返回后调用texit
  • rt_hw_context_switch_to( )

    • 作用:
      • 切换到to指向的上下文指针变量cp所指向的上下文context
  • rt_hw_context_switch( )

    • 作用:
      • 切换到to指向的上下文指针变量cp所指向的上下文context
      • 额外将当前上下文的指针cp写入from指向的上下文指针变量中
    • 调用rt_thread_self()返回当前线程的PCB
    • 将当前pcb中的user_data存到局部变量中
    • 然后将 to 的数据写入当前pcb的user_data中
    • 将from的值赋值为当前的pcb的context
    • 调用yield,跳转到ev_handler
    • 从yield返回后,恢复 user data
  • ev_handler() (在这里返回切换后的context)

    • 添加case识别出EVENT_YIELD事件后,
    • 从pcb中的user data读出to
    • 将to的值赋值给传入的c,并返回

思考题

  1. 如果不同的进程共享同一个栈空间, 会发生什么呢?
    1. 数据冲突:栈是用于存储局部变量和函数调用信息的,每个进程都有自己的栈空间。如果多个进程共享同一个栈,局部变量可能会被其他进程修改,导致数据不一致和不可预测的行为。
    2. 栈溢出:栈的大小是有限的,如果多个进程同时使用同一个栈,可能会导致栈溢出,进而引发程序崩溃或未定义行为。
    3. 安全性问题:共享栈空间可能导致安全漏洞,恶意进程可以修改其他进程的栈内容,从而执行任意代码或获取敏感信息。
    4. 调试困难:由于栈内容的混乱,调试程序时会变得非常困难,难以追踪错误的来源。
    5. 上下文切换问题:操作系统在进行进程切换时,通常会保存和恢复每个进程的栈状态。如果栈被多个进程共享,可能会导致上下文切换时的状态不一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值