返回

Linux 0.11 源码分析 - 写时复制的实现

Android

引言:

写时复制(Copy-on-Write)是一种内存管理技术,允许多个进程共享同一页物理内存,直到其中一个进程尝试写入该页时,才会为该进程创建一个该页的副本。这样可以节省内存空间,并提高系统性能。

Linux 0.11 中的写时复制:

在 Linux 0.11 内核中,写时复制主要通过页表来实现。当进程第一次访问一个页面时,如果该页面不在物理内存中,那么内核会从磁盘上加载该页面到物理内存中,并创建一个新的页表项来映射该页面。

写时复制的步骤:

  1. 当一个进程尝试写入一个只读页面时,硬件会引发一个页面错误中断。
  2. 内核捕获这个中断,并检查页面错误的原因。
  3. 如果页面错误的原因是写保护,那么内核会创建一个该页面的副本,并将该副本分配给该进程。
  4. 内核然后修改页表,使该进程的页表项指向该页面的副本。
  5. 进程可以继续执行,并对该页面的副本进行写入操作。

示例代码:

/* 在页面错误中断处理程序中 */
static int do_wp_page(struct task_struct *tsk, struct vm_area_struct *vma,
                      unsigned long address, int write_access)
{
    struct page *page;
    void *kaddr;
    int err;

    /* 获取页面的副本 */
    page = alloc_page(GFP_HIGHUSER);
    if (!page)
        return -ENOMEM;

    /* 将页面映射到内核地址空间 */
    kaddr = page_address(page);
    err = map_page_dirty(vma, address & PAGE_MASK, page);
    if (err) {
        put_page(page);
        return err;
    }

    /* 将页面的内容从旧页面复制到新页面 */
    copy_page(kaddr, vma->vm_file->f_op->mmap(vma, address & PAGE_MASK, PAGE_SIZE,
                                                PROT_READ | PROT_WRITE));

    /* 取消映射页面 */
    unmap_page(kaddr);

    /* 将新页面添加到进程的页表中 */
    set_pte_vaddr(tsk, address, mk_pte(page, vma->vm_page_prot));

    /* 继续执行 */
    tsk->thread.regs->pc += 2;
    return 0;
}

总结:

写时复制是一种有效的内存管理技术,可以节省内存空间,并提高系统性能。Linux 0.11 内核中的写时复制是通过页表来实现的,当进程第一次访问一个页面时,如果该页面不在物理内存中,那么内核会从磁盘上加载该页面到物理内存中,并创建一个新的页表项来映射该页面。当一个进程尝试写入一个只读页面时,硬件会引发一个页面错误中断,内核捕获这个中断,并检查页面错误的原因。如果页面错误的原因是写保护,那么内核会创建一个该页面的副本,并将该副本分配给该进程。内核然后修改页表,使该进程的页表项指向该页面的副本。进程可以继续执行,并对该页面的副本进行写入操作。