【内核资料】fork写时拷贝实现原理

作者:Leosocy

链接:https://blog.leosocy.top/深入了解Linux-COW写时拷贝实现原理/

为了节约物理内存,减少进程创建时资源和时间的消耗,父进程在调用 fork() 生成子进程时,子进程与父进程会共享同一内存区。只有当其中一进程进行写操作时,系统才会为其另外分配内存页面。这就是写时复制机制 (copy on write) 的意思。那么 Linux 内核是如何实现这种机制的呢,今天我们来简要的分析一下。

fork 系统调用流程

sys_fork -> _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0) -> copy_process() -> copy_mm(clone_flags, p)
static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
{
    struct mm_struct *mm, *oldmm;
    ...
    if (clone_flags & CLONE_VM) {
        mmget(oldmm);
        mm = oldmm;
        goto good_mm;
    }
    retval = -ENOMEM;
    mm = dup_mm(tsk);
    ...
good_mm:
    tsk->mm = mm;
    tsk->active_mm = mm;
    return 0;
fail_nomem:
    return retval;
}

copy_mm 的逻辑为,如果 clone_flags 指定了 CLONE_VM,对应的 clone() 系统调用创建线程,则共享父进程的 mm 结构;否则属于创建进程需要调用 dup_mm,dup_mm 进而调用 dup_mmap 函数。

dup_mm 先给子进程分配了一个新的结构体,然后调用 dup_mmap 拷贝父进程地址空间,所以我们再进入 dup_mmap 看看拷贝了什么东西,因为 dup_mmap 函数代码太长就不贴出来了,直接看 copy_page_range 函数,这个函数负责页表得拷贝,我们知道 Linux 从 2.6.11 开始采用四级分页模型,分别是 pgd、pud、pmd、pte,所以从 copy_page_range 一直调用到 copy_pte_range 都是拷贝相应的页表条目,最后我们再来看看 copy_pte_range 调用的 copy_one_pte 函数

static inline void
copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma,
        unsigned long addr, int *rss)
{
    unsigned long vm_flags = vma->vm_flags;
    pte_t pte = *src_pte;
    struct page *page;
    ...
    /*
     * If it's a COW mapping, write protect it both
     * in the parent and the child
     */
    if (is_cow_mapping(vm_flags)) {
        ptep_set_wrprotect(src_mm, addr, src_pte);
        pte = pte_wrprotect(pte);
    }
    ...

out_set_pte:
    set_pte_at(dst_mm, addr, dst_pte, pte);
}

上面的代码判断如果父进程的页支持写时复制,就将父子进程的页都置为写保护,清除 pte 的_PAGE_BIT_RW 标记。

至此 fork 系统调用就完成了,那么当父进程或者子进程尝试写共享物理页时,内核是怎么拷贝物理页面的呢?

写共享物理页

当父进程 A 或子进程 B 任何一方对这些已共享的物理页面执行写操作时,都会产生页面出错异常(page_fault int14)中断,会将flags & FAULT_FLAG_WRITE,然后通过do_page_fault() -> handle_mm_fault() -> handle_pte_fault()调用链解决这个异常。

// do_page_fault()中,经过在vma中检查后,
// 判定访问地址在进程虚拟空间内,所继续执行的代码段。
good_area:
info.si_code = SEGV_ACCERR
write = 0;
if (error_code & 2) { /* write access */
	if (!(vma->vm_flags & VM_WRITE)
		goto bad area;
    write++;
} else
/* read access*/
if ((error code & 1) || !(vma->vm flags &(VM_READ & VM_EXEC))
	goto bad_area;

很明显可以看到,这里使用vma->vm_flags来判断,发生的异常是否符合线性区内页面的读写权限。

利用虚拟页面权限 + 物理页面权限的组合判定,产生了写时复制之类的技术。

static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
{
    ...
    if (vmf->flags & FAULT_FLAG_WRITE) {
        if (!pte_write(entry))
            return do_wp_page(vmf);
        entry = pte_mkdirty(entry);
    }
    ...
}

pte_write 会根据 pte_flags(pte) & _PAGE_RW 判断页是否有写保护,这个标记是之前 fork 时 clear 掉的,所以会接着调用do_wp_page

/*
 * This routine handles present pages, when users try to write
 * to a shared page. It is done by copying the page to a new address
 * and decrementing the shared-page counter for the old page.
 * 当用户试图写入共享页面时,此例程处理当前页面。将页面复制到一个新地址并减少旧页面的共享页面计数器。
 * ...
 */
static vm_fault_t do_wp_page(struct vm_fault *vmf)
    __releases(vmf->ptl)
{
    ...
    return wp_page_copy(vmf);
}

/*
 * Handle the case of a page which we actually need to copy to a new page.
 *
 * Called with mmap_sem locked and the old page referenced, but
 * without the ptl held.
 *
 * High level logic flow:
 *
 * - Allocate a page, copy the content of the old page to the new one.
 * - Handle book keeping and accounting - cgroups, mmu-notifiers, etc.
 * - Take the PTL. If the pte changed, bail out and release the allocated page
 * - If the pte is still the way we remember it, update the page table and all
 *   relevant references. This includes dropping the reference the page-table
 *   held to the old page, as well as updating the rmap.
 * - In any case, unlock the PTL and drop the reference we took to the old page.
 */
static vm_fault_t wp_page_copy(struct vm_fault *vmf)

wp_page_copy 函数就不具体分析了,主要就是分配一个页面,将旧页面的内容复制到新页面。

至此,父进程子进程各自拥有一块内容相同的物理页面。最后,从异常处理函数中返回时,CPU 就会重新执行刚才导致异常的写入操作指令,使进程继续执行下去。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值