Speed up system calls (easy)
一些操作系统(比如 Linux)会通过在用户空间和内核之间共享只读区域来加速特定的系统调用。这可以消除系统调用的消耗。这里只要求对getpid()
加速。
当每个进程被创建时,可以在USYSCALL
上映射一个只读页。USYSCALL
是定义在memlayout.h
中定义的虚拟内存。在这一页的开始,保存一个struct usyscall
(这个结构体也定义在 memlayout.h
),并且初始化它来保存当前进程的PID。 对于这个实验,ugetpid()
已经在用户空间提供了,并且会自动使用USYSCALL
映射。
一些提示:
- 可以在
kernel/proc.c
里的proc_pagetable()
里执行这个映射。 - 选择合适的权限位,允许用户空间可以访问这个页
mappages()
很有用- 不要忘了使用
allocproc()
初始化页 - 确保使用
freeproc()
释放页
分析
ugetpid()
int
ugetpid(void)
{
struct usyscall *u = (struct usyscall *)USYSCALL;
return u->pid;
}
这里直接拿了一个地址转换成 struct ussycall
.
映射到页
结构体proc
struct proc {
...
// these are private to the process, so p->lock need not be held.
uint64 kstack; // Virtual address of kernel stack
uint64 sz; // Size of process memory (bytes)
pagetable_t pagetable; // User page table
struct trapframe *trapframe; // data page for trampoline.S
struct context context; // swtch() here to run process
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
};
这里发现一个trapframe
,现在就照着这个变量写。
// kernel/proc.c
struct proc {
// these are private to the process, so p->lock need not be held.
uint64 kstack; // Virtual address of kernel stack
uint64 sz; // Size of process memory (bytes)
pagetable_t pagetable; // User page table
struct trapframe *trapframe; // data page for trampoline.S
struct usyscall *usyscall_frame; // Add a data page for usyscall
struct context context; // swtch() here to run process
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
};
初始化 usyscall_frame
// kernel/proc.c : allocproc
/ Look in the process table for an UNUSED proc.
// If found, initialize state required to run in the kernel,
// and return with p->lock held.
// If there are no free procs, or a memory allocation fails, return 0.
static struct proc*
allocproc(void)
{
struct proc *p;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock)