我的问题是 mprotect
有多快。相比于保护1MB连续内存,保护1GB的连续内存会有什么区别?当然,我可以测量时间,但我想知道底层发生了什么。
快速检查源代码似乎表明它会遍历所选区域中的进程映射并更改它们的标志。如果你保护不到整个映射,它将把它分成两个或三个。
因此,简而言之,它的时间复杂度是 O(n)
,其中 n
是您调用 mmap 的次数。
您可以在 /proc/pid/maps
中查看所有当前映射。
在该区域,每页计数的时间复杂度为O(n),因为它需要更改所有PTE(页面转换条目)上的访问位(PTE描述PageTable中的虚拟->物理页面映射)。调用树:
mprotect
->
mprotect_fixup
->
change_pte_range
http://lxr.free-electrons.com/source/mm/mprotect.c#L32
47 do {
48 oldpte = *pte;
49 if (pte_present(oldpte)) {
50 pte_t ptent;
51
52 ptent = ptep_modify_prot_start(mm, addr, pte);
53 ptent = pte_modify(ptent, newprot);
54
55 /*
56 * Avoid taking write faults for pages we know to be
57 * dirty.
58 */
59 if (dirty_accountable && pte_dirty(ptent))
60 ptent = pte_mkwrite(ptent);
61
62 ptep_modify_prot_commit(mm, addr, pte, ptent);
63 } else if (PAGE_MIGRATION && !pte_file(oldpte)) {
64 swp_entry_t entry = pte_to_swp_entry(oldpte);
65
66 if (is_write_migration_entry(entry)) {
67 /*
68 * A protection check is difficult so
69 * just be safe and disable write
70 */
71 make_migration_entry_read(&entry);
72 set_pte_at(mm, addr, pte,
73 swp_entry_to_pte(entry));
74 }
75 }
76 } while (pte++, addr += PAGE_SIZE, addr != end);
addr += PAGE_SIZE, addr != end);