structproc { ... pagetable_t pagetable; // User page table structtrapframe *trapframe;// data page for trampoline.S structusyscall *usyscall;// data page for USYSCALL structcontextcontext;// swtch() here to run process ... };
这样就可以通过p->usyscall来获取了。
在memlayout.h中我们可以看到用户态空间内存布局:
1 2 3 4 5 6 7 8 9
Address zero first: text original data and bss fixed-size stack expandable heap ... USYSCALL (shared with kernel) TRAPFRAME (p->trapframe, used by the trampoline) TRAMPOLINE (the same page as in the kernel)
// map the trampoline code (for system call return) // at the highest user virtual address. // only the supervisor uses it, on the way // to/from user space, so not PTE_U. if(mappages(pagetable, TRAMPOLINE, PGSIZE, (uint64)trampoline, PTE_R | PTE_X) < 0){ uvmfree(pagetable, 0); return0; }
// map the trapframe page just below the trampoline page, for // trampoline.S. if(mappages(pagetable, TRAPFRAME, PGSIZE, (uint64)(p->trapframe), PTE_R | PTE_W) < 0){ uvmunmap(pagetable, TRAMPOLINE, 1, 0); uvmfree(pagetable, 0); return0; }