什么是陷阱框?陷阱帧和 task_struct 之间有什么区别?

Tar*_*tel 5 unix linux linux-kernel xv6

task_struct 用于存储 CPU 的状态,trap frame 做同样的事情,那么它们有什么不同呢?而陷阱帧是一个数据结构还是一个公正的概念?

Ale*_*pus 8

cpu 状态 - 与上下文切换有关,而 trapframe 则在出现异常或 irq 后保存保存在 tcb 中的用户空间状态。

我的解释将基于树莓派2(ARMv7)的自写操作系统

这是任务结构体,它存储上下文和陷阱帧:

class task {
private:
public:
    uint32_t pid;
    pde_t *pgd;
    tstate state;
    uint32_t *kstack;
    context *ctx;
    trapframe *tf;
    task() {};
    void init_vm();
    int load_binary(char *binary_obj);
};
Run Code Online (Sandbox Code Playgroud)

上下文是一组被调用者保存的寄存器,它表示任务被其他任务抢占之前的状态(上下文切换)

struct context {
    uint32_t    r4;
    uint32_t    r5;
    uint32_t    r6;
    uint32_t    r7;
    uint32_t    r8;
    uint32_t    r9;
    uint32_t    r10;
    uint32_t    r11;
    uint32_t    r12;
    uint32_t    lr;
};
Run Code Online (Sandbox Code Playgroud)

当调度程序中发生上下文切换时,当前任务将其寄存器保存到*ctx in class task,并从下一个任务加载新的寄存器集:

请注意,下面示例中的 R0 是 THIS 指针,因为我们调用特定对象的方法。所以参数是 R1 和 R2

void scheduler::swtch(struct context **oldctx, struct context *newctx)
{
    /* r0-r3 are not preserved during call, no need to save them */
    asm volatile("push {r4-r12, lr}");
    /* save current kernel thread sp to oldctx */
    asm volatile("str r13, [r1]");
    /* Load newctx (new sp) to sp register */
    asm volatile("mov r13, r2");
    /* Load all other registers from new ctx,
     *  refer struct context format for details */
    asm volatile("pop {r4-r12, lr}");
}
Run Code Online (Sandbox Code Playgroud)

现在关于陷阱框架:

struct trapframe {
    uint32_t   sp_usr;     // user mode sp
    uint32_t   lr_usr;     // user mode lr
    uint32_t   sp_svc;
    uint32_t   lr_svc;
    uint32_t   spsr;
    uint32_t   r[N_GEN_REGS];
    uint32_t   pc;         // (lr on entry) instruction to resume execution
};
Run Code Online (Sandbox Code Playgroud)

Trapframe存储在异常发生时保存的寄存器组,因此使用trapframe我们可以返回并继续执行(当异常或irq将被处理时)


koo*_*koo 5

澄清一下,task_struct包含进程的信息,而不是 cpu 的信息。操作系统可以管理多个进程,因此可能存在多个实例task_struct

Trapframe保存用户空间寄存器。当 cpu 从用户模式更改为内核模式(例如xv6-riscv 中的管理模式)时,它会保存用户空间寄存器。

当然trapframe是一种数据结构。

您可以在下面的链接中看到 trapframe 的样子,请参阅proc.hproc.c

https://github.com/mit-pdos/xv6-public