๏ปฟ# madvise / process_madvise
๊ด๋ จ ์์ค: mm/madvise.c, include/uapi/asm-generic/mman-common.h, include/linux/mm.h
๊ฐ์ (Overview)
madvise()๋ ์ฌ์ฉ์ ํ๋ก์ธ์ค๊ฐ ์ปค๋์๊ฒ ํน์ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ํ ํํธ(hint)๋ฅผ ์ ๊ณตํ๋ ์์คํ
ํธ์ถ์ด๋ค. readahead ์ ์ฑ
๋ณ๊ฒฝ, ํ์ด์ง ํด์ , ์ค์์์, THP ๋ณํฉ, KSM ๋ณํฉ ๋ฑ ๋ค์ํ ๋์์ ๋จ์ผ ์ง์
์ ์ ํตํด ์ฒ๋ฆฌํ๋ค. Linux 7.0์์๋ madvise_behavior ๊ตฌ์กฐ์ฒด๋ฅผ ์ค์ฌ์ผ๋ก locking, VMA walk, ๊ฐ behavior๋ณ ๋ถ๊ธฐ ์ฒ๋ฆฌ๊ฐ ์ฒด๊ณํ๋์ด ์์ผ๋ฉฐ, process_madvise()๋ฅผ ํตํด ์๊ฒฉ ํ๋ก์ธ์ค์๋ ์ ์ฉํ ์ ์๋ค.
ํต์ฌ ์์ค ํ์ผ:
mm/madvise.c โ ์์คํ
ํธ์ถ ๊ตฌํ, behavior ๋ถ๊ธฐ, VMA walk, ํ์ด์ง ํ
์ด๋ธ ์กฐ์
include/uapi/asm-generic/mman-common.h โ MADV_* ์์ ์ ์ (0~25, 100~103)
include/linux/mm.h โ VM_* ํ๋๊ทธ (VM_DONTCOPY, VM_WIPEONFORK, VM_SEQ_READ, VM_RAND_READ, VM_DONTDUMP)
include/linux/mman.h โ VMA ์์ ๊ด๋ จ ํฌํผ
๋น ๋ฅธ ์ ๊ฒ ๋ช
๋ น
# ํ์ฌ ํ๋ก์ธ์ค์ madvise ์ฌ์ฉ ํต๊ณ ํ์ธ (perf)
perf stat -e 'syscalls:sys_enter_madvise' -a sleep 1
# VMA flag ๋ณ๊ฒฝ ์ถ์ (ftrace)
echo 1 > /sys/kernel/debug/tracing/events/syscalls/sys_enter_madvise/enable
cat /sys/kernel/debug/tracing/trace_pipe
# madvise ๊ด๋ จ ์ปค๋ ์ฌ๋ณผ ํ์ธ
cat /proc/kallsyms | grep -E 'do_madvise|process_madvise|madvise_walk'
# process_madvise syscall ์ถ์
perf stat -e 'syscalls:sys_enter_process_madvise' -a sleep 1
# ํน์ ํ๋ก์ธ์ค์ VMA flags ํ์ธ (madvise ๊ฒฐ๊ณผ ๊ด์ฐฐ)
cat /proc/<PID>/maps | head -20
# THP collapse ์ํ ํ์ธ (MADV_COLLAPSE ๊ด๋ จ)
cat /sys/kernel/mm/transparent_hugepage/enabled
# KSM ์ํ ํ์ธ (MADV_MERGEABLE ๊ด๋ จ)
cat /sys/kernel/mm/ksm/run
cat /sys/kernel/mm/ksm/pages_shared
# ๋ฉ๋ชจ๋ฆฌ ํ์ ์ํ ํ์ธ (MADV_COLD/PAGEOUT ๊ด๋ จ)
cat /proc/vmstat | grep -E 'pgscan|pgsteal|pgdeactivate'
ํต์ฌ ์๋ฃ๊ตฌ์กฐ
madvise_behavior โ behavior ์ฒ๋ฆฌ ์ํ ์ปจํ
์ด๋
// mm/madvise.c:66-82
struct madvise_behavior {
struct mm_struct *mm; // ๋์ ํ๋ก์ธ์ค์ mm_struct
int behavior; // MADV_* ์์ ๊ฐ
struct mmu_gather *tlb; // TLB batch ์์ง๊ธฐ
enum madvise_lock_mode lock_mode; // ์ ๊ธ ๋ชจ๋ ๊ฒฐ์
struct anon_vma_name *anon_name; // ์ต๋ช
VMA ์ด๋ฆ (__MADV_SET_ANON_VMA_NAME์ฉ)
struct madvise_behavior_range range; // ํ์ฌ ์ฒ๋ฆฌ ์ค์ธ ์ฃผ์ ๋ฒ์
struct vm_area_struct *prev; // ์ด์ VMA (VMA split/merge์ฉ)
struct vm_area_struct *vma; // ํ์ฌ ๋์ VMA
bool lock_dropped; // mmap_lock ํด์ ์ฌ๋ถ ์ถ์
};
lock_dropped: MADV_WILLNEED์์ vfs_fadvise() ํธ์ถ ์ mmap_lock์ ํด์ ํ๋ฏ๋ก, ์ดํ VMA ์ฌํ์์ด ํ์ํจ
lock_mode: behavior๋ณ๋ก MADVISE_NO_LOCK, MADVISE_MMAP_READ_LOCK, MADVISE_MMAP_WRITE_LOCK, MADVISE_VMA_READ_LOCK ์ค ์ ํ
madvise_lock_mode โ ์ ๊ธ ๋ชจ๋ ์ด๊ฑฐํ
// mm/madvise.c:54-59
enum madvise_lock_mode {
MADVISE_NO_LOCK, // ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ ์ฃผ์
์ ์ ๊ธ ๋ถํ์
MADVISE_MMAP_READ_LOCK, // mmap_lock ์ฝ๊ธฐ ์ ๊ธ (WILLNEED, COLD, PAGEOUT ๋ฑ)
MADVISE_MMAP_WRITE_LOCK, // mmap_lock ์ฐ๊ธฐ ์ ๊ธ (vm_flags ๋ณ๊ฒฝ ์)
MADVISE_VMA_READ_LOCK, // VMA ์ฝ๊ธฐ ์ ๊ธ (DONTNEED, FREE, GUARD ๋ฑ)
};
madvise_behavior_range โ ์ฒ๋ฆฌ ๋ฒ์
// mm/madvise.c:61-64
struct madvise_behavior_range {
unsigned long start; // ์์ ๊ฐ์ ์ฃผ์ (ํ์ด์ง ์ ๋ ฌ)
unsigned long end; // ์ข
๋ฃ ๊ฐ์ ์ฃผ์ (exclusive)
};
madvise_walk_private โ ํ์ด์ง ํ
์ด๋ธ walk ๋น๊ณต๊ฐ ๋ฐ์ดํฐ
// mm/madvise.c:49-52
struct madvise_walk_private {
struct mmu_gather *tlb; // TLB ์์ง ์ปจํ
์คํธ
bool pageout; // true = MADV_PAGEOUT, false = MADV_COLD
};
ํต์ฌ ํจ์
do_madvise โ ์์คํ
ํธ์ถ ๋ฉ์ธ ์ง์
์
// mm/madvise.c:2012-2033
int do_madvise(struct mm_struct *mm, unsigned long start,
size_t len_in, int behavior)
{
int error;
struct mmu_gather tlb;
struct madvise_behavior madv_behavior = {
.mm = mm,
.behavior = behavior,
.tlb = &tlb,
};
if (madvise_should_skip(start, len_in, behavior, &error))
return error;
error = madvise_lock(&madv_behavior); // behavior๋ณ ์ ๊ธ ํ๋
if (error)
return error;
madvise_init_tlb(&madv_behavior); // TLB batch ์ด๊ธฐํ
error = madvise_do_behavior(start, len_in, &madv_behavior);
madvise_finish_tlb(&madv_behavior); // TLB batch ํด์
madvise_unlock(&madv_behavior); // ์ ๊ธ ํด์
return error;
}
ํ๋ฆ: ๊ฒ์ฆ โ ์ ๊ธ โ TLB ์ด๊ธฐํ โ behavior ์ฒ๋ฆฌ โ TLB ๋ง๋ฌด๋ฆฌ โ ์ ๊ธ ํด์
process_madvise โ pidfd ๊ธฐ๋ฐ ์๊ฒฉ ์ ์ฉ ์ง์
์
// mm/madvise.c:2107-2168
SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
size_t, vlen, int, behavior, unsigned int, flags)
{
ssize_t ret;
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack;
struct iov_iter iter;
struct task_struct *task;
struct mm_struct *mm;
unsigned int f_flags;
if (flags != 0) {
ret = -EINVAL;
goto out;
}
ret = import_iovec(ITER_DEST, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
if (ret < 0)
goto out;
task = pidfd_get_task(pidfd, &f_flags);
if (IS_ERR(task)) {
ret = PTR_ERR(task);
goto free_iov;
}
/* ASLR ๋ฉํ๋ฐ์ดํฐ ์ ์ถ์ ๋ง๊ธฐ ์ํด PTRACE_MODE_READ๋ฅผ ์๊ตฌํ๋ค. */
mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
if (IS_ERR(mm)) {
ret = PTR_ERR(mm);
goto release_task;
}
/* ์๊ฒฉ ์ฃผ์ ๊ณต๊ฐ์ ๊ฑด๋๋ฆด ๋๋ง behavior ์ ํ์ ์ ์ฉํ๋ค. */
if (mm != current->mm && !process_madvise_remote_valid(behavior)) {
ret = -EINVAL;
goto release_mm;
}
/* ์๊ฒฉ ๋์์๋ CAP_SYS_NICE๊ฐ ํ์ํ๋ค. */
if (mm != current->mm && !capable(CAP_SYS_NICE)) {
ret = -EPERM;
goto release_mm;
}
ret = vector_madvise(mm, &iter, behavior);
release_mm:
mmput(mm);
release_task:
put_task_struct(task);
free_iov:
kfree(iov);
out:
return ret;
}
process_madvise_remote_valid()๋ MADV_COLD, MADV_PAGEOUT, MADV_WILLNEED, MADV_COLLAPSE๋ง ํ์ฉํ๋ค.
vector_madvise()๋ iovec๋ฅผ ์ํํ๋ฉด์ ๊ฐ ๊ตฌ๊ฐ์ ๊ฐ์ madvise ์ฒ๋ฆฌ ๊ฒฝ๋ก๋ก ๋๊ธด๋ค.
madvise_vma_behavior โ behavior๋ณ ๋ถ๊ธฐ ๋์คํจ์ฒ
// mm/madvise.c:1345-1448
static int madvise_vma_behavior(struct madvise_behavior *madv_behavior)
{
int behavior = madv_behavior->behavior;
struct vm_area_struct *vma = madv_behavior->vma;
vm_flags_t new_flags = vma->vm_flags;
struct madvise_behavior_range *range = &madv_behavior->range;
int error;
if (unlikely(!can_madvise_modify(madv_behavior)))
return -EPERM;
switch (behavior) {
case MADV_REMOVE: return madvise_remove(madv_behavior);
case MADV_WILLNEED: return madvise_willneed(madv_behavior);
case MADV_COLD: return madvise_cold(madv_behavior);
case MADV_PAGEOUT: return madvise_pageout(madv_behavior);
case MADV_FREE:
case MADV_DONTNEED:
case MADV_DONTNEED_LOCKED: return madvise_dontneed_free(madv_behavior);
case MADV_COLLAPSE:
return madvise_collapse(vma, range->start, range->end,
&madv_behavior->lock_dropped);
case MADV_GUARD_INSTALL: return madvise_guard_install(madv_behavior);
case MADV_GUARD_REMOVE: return madvise_guard_remove(madv_behavior);
// VMA ํ๋๊ทธ ๋ณ๊ฒฝ (madvise_update_vma ํธ์ถ)
case MADV_NORMAL:
new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ;
break;
case MADV_SEQUENTIAL:
new_flags = (new_flags & ~VM_RAND_READ) | VM_SEQ_READ;
break;
case MADV_RANDOM:
new_flags = (new_flags & ~VM_SEQ_READ) | VM_RAND_READ;
break;
case MADV_DONTFORK:
new_flags |= VM_DONTCOPY;
break;
case MADV_DOFORK:
if (new_flags & VM_SPECIAL)
return -EINVAL;
new_flags &= ~VM_DONTCOPY;
break;
case MADV_WIPEONFORK:
if (vma->vm_file || new_flags & VM_SHARED)
return -EINVAL;
new_flags |= VM_WIPEONFORK;
break;
case MADV_KEEPONFORK:
if (new_flags & VM_DROPPABLE)
return -EINVAL;
new_flags &= ~VM_WIPEONFORK;
break;
case MADV_DONTDUMP:
new_flags |= VM_DONTDUMP;
break;
case MADV_DODUMP:
if ((!is_vm_hugetlb_page(vma) && (new_flags & VM_SPECIAL)) ||
(new_flags & VM_DROPPABLE))
return -EINVAL;
new_flags &= ~VM_DONTDUMP;
break;
case MADV_MERGEABLE:
case MADV_UNMERGEABLE:
error = ksm_madvise(vma, range->start, range->end,
behavior, &new_flags);
if (error)
goto out;
break;
case MADV_HUGEPAGE:
case MADV_NOHUGEPAGE:
error = hugepage_madvise(vma, &new_flags, behavior);
if (error)
goto out;
break;
}
/* ์ด ๋ถ๊ธฐ๋ VMA ์์ ๊ฒฝ๋ก๋ค. */
VM_WARN_ON_ONCE(madv_behavior->lock_mode != MADVISE_MMAP_WRITE_LOCK);
error = madvise_update_vma(new_flags, madv_behavior);
out:
/* ๋ฉ๋ชจ๋ฆฌ ์์์ด ์ผ์์ ์ผ๋ก ๋ถ์กฑํ๋ฉด EAGAIN์ผ๋ก ๋ณํํ๋ค. */
if (error == -ENOMEM)
error = -EAGAIN;
return error;
}
madvise_walk_vmas โ VMA ์ํ + behavior ์ ์ฉ
// mm/madvise.c:1668-1742
static int madvise_walk_vmas(struct madvise_behavior *madv_behavior)
{
struct mm_struct *mm = madv_behavior->mm;
struct madvise_behavior_range *range = &madv_behavior->range;
unsigned long last_end = range->end;
int unmapped_error = 0;
int error;
struct vm_area_struct *prev, *vma;
// VMA read lock ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๋จ์ผ VMA ์๋
if (madv_behavior->lock_mode == MADVISE_VMA_READ_LOCK &&
try_vma_read_lock(madv_behavior)) {
error = madvise_vma_behavior(madv_behavior);
vma_end_read(madv_behavior->vma);
return error;
}
vma = find_vma_prev(mm, range->start, &prev);
if (vma && range->start > vma->vm_start)
prev = vma;
// VMA ์ํ ๋ฃจํ
for (;;) {
if (!vma)
return -ENOMEM;
if (range->start < vma->vm_start) {
unmapped_error = -ENOMEM;
range->start = vma->vm_start;
if (range->start >= last_end)
break;
}
range->end = min(vma->vm_end, last_end);
error = madvise_vma_behavior(madv_behavior);
if (error)
return error;
if (madv_behavior->lock_dropped) {
// mmap_lock์ ๋ด๋ ค์ VMA ์ฐธ์กฐ๋ฅผ ์ ์งํ ์ ์๋ ๊ฒฝ์ฐ
prev = NULL;
vma = NULL;
madv_behavior->lock_dropped = false;
} else {
vma = madv_behavior->vma;
prev = vma;
}
if (vma && range->end < vma->vm_end)
range->end = vma->vm_end;
if (range->end >= last_end)
break;
vma = find_vma(mm, vma ? vma->vm_end : range->end);
range->start = range->end;
}
return unmapped_error;
}
madvise_cold_or_pageout_pte_range โ PTE ์์ค ํ์ด์ง ๋นํ์ฑํ/์ถ๋ ฅ
// mm/madvise.c:352-565 (ํต์ฌ ๋ฃจํ)
static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,
unsigned long addr, unsigned long end, struct mm_walk *walk)
{
// THP ์ฒ๋ฆฌ: pmd_trans_huge ํ์ธ โ split ๋๋ ์ง์ ์ฒ๋ฆฌ
// ์ผ๋ฐ PTE ๋ฃจํ:
for (; addr < end; pte += nr, addr += nr * PAGE_SIZE) {
ptent = ptep_get(pte);
folio = vm_normal_folio(vma, addr, ptent);
// Large folio โ madvise_folio_pte_batch()๋ก ์ผ๊ด ์ฒ๋ฆฌ
// LRU ํ
์คํธ ์คํจ ๋๋ mapcount ๋ถ์ผ์น ์ ๊ฑด๋๋
if (!pageout && pte_young(ptent))
clear_young_dirty_ptes(vma, addr, pte, nr, CYDP_CLEAR_YOUNG); // COLD
folio_clear_referenced(folio);
if (pageout)
list_add(&folio->lru, &folio_list); // PAGEOUT: LRU์์ ๊ฒฉ๋ฆฌ
else
folio_deactivate(folio); // COLD: activeโinactive ์ด๋
}
if (pageout)
reclaim_pages(&folio_list); // PAGEOUT: ์ฆ์ ํ์
}
madvise_free_pte_range โ lazyfree ๋งํน
// mm/madvise.c:651-782 (ํต์ฌ ๋ก์ง)
static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
unsigned long end, struct mm_walk *walk)
{
for (; addr != end; pte += nr, addr += PAGE_SIZE * nr) {
ptent = ptep_get(pte);
// swap entry โ PTE ํด๋ฆฌ์ด (์ค์์ธ๋ณด๋ค ํ์ด์ง ํ ๋น+์ ๋ก์์ด ์ ๋ ด)
if (!pte_present(ptent)) {
if (softleaf_is_swap(entry))
swap_put_entries_direct(entry, nr);
continue;
}
folio = vm_normal_folio(vma, addr, ptent);
// swap cache ๋๋ dirty โ folio_free_swap ์๋, dirty ํด์
if (folio_test_swapcache(folio) || folio_test_dirty(folio)) {
if (!folio_free_swap(folio)) continue;
folio_clear_dirty(folio);
}
// young/dirty PTE ํด๋ฆฌ์ด
if (pte_young(ptent) || pte_dirty(ptent))
clear_young_dirty_ptes(vma, addr, pte, nr, cydp_flags);
folio_mark_lazyfree(folio); // lazyfree๋ก ํ์ โ ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ ์ ์๋ ํด์
}
}
ํธ์ถ ํ๋ฆ
SYSCALL_DEFINE3(madvise, ...)
โโโ do_madvise(mm, start, len_in, behavior)
โโโ madvise_should_skip() โ ์ ํจ์ฑ ๊ฒ์ฆ
โโโ madvise_lock() โ behavior๋ณ ์ ๊ธ ์ ํ
โ โโโ get_lock_mode()
โโโ madvise_init_tlb() โ TLB batch ์ด๊ธฐํ
โโโ madvise_do_behavior()
โ โโโ [MADV_HWPOISON/SOFT_OFFLINE] โ madvise_inject_error()
โ โโโ [MADV_POPULATE_*] โ madvise_populate()
โ โ โโโ faultin_page_range()
โ โโโ [๊ธฐํ] โ madvise_walk_vmas()
โ โโโ try_vma_read_lock() โ VMA lock ์ฐ์ ์๋
โ โโโ madvise_vma_behavior() โ behavior๋ณ ๋ถ๊ธฐ
โ โโโ MADV_WILLNEED โ madvise_willneed()
โ โ โโโ [anon] โ swapin_walk_pmd_entry()
โ โ โโโ [shmem] โ shmem_swapin_range()
โ โ โโโ [file] โ vfs_fadvise(POSIX_FADV_WILLNEED)
โ โโโ MADV_COLD โ madvise_cold()
โ โ โโโ madvise_cold_page_range()
โ โ โโโ madvise_cold_or_pageout_pte_range(pageout=false)
โ โ โโโ folio_deactivate()
โ โโโ MADV_PAGEOUT โ madvise_pageout()
โ โ โโโ madvise_pageout_page_range()
โ โ โโโ madvise_cold_or_pageout_pte_range(pageout=true)
โ โ โโโ reclaim_pages()
โ โโโ MADV_DONTNEED/FREE โ madvise_dontneed_free()
โ โ โโโ [DONTNEED] โ zap_page_range_single_batched()
โ โ โโโ [FREE] โ madvise_free_single_vma()
โ โ โโโ madvise_free_pte_range() โ folio_mark_lazyfree()
โ โโโ MADV_REMOVE โ madvise_remove()
โ โ โโโ vfs_fallocate(PUNCH_HOLE)
โ โโโ MADV_COLLAPSE โ madvise_collapse()
โ โโโ MADV_GUARD_INSTALL โ madvise_guard_install()
โ โ โโโ walk_page_range โ guard marker PTE ์ค์น
โ โโโ MADV_GUARD_REMOVE โ madvise_guard_remove()
โ โโโ [VMA ํ๋๊ทธ] โ madvise_update_vma()
โ โโโ vma_modify_flags() / vma_modify_name()
โโโ madvise_finish_tlb()
โโโ madvise_unlock()
์กฐ๊ฑด๋ณ ๋น๊ต
behavior๋ณ ์ ๊ธ ๋ชจ๋
| behavior | ์ ๊ธ ๋ชจ๋ | ์ค๋ช
|
| `MADV_DONTNEED`, `MADV_DONTNEED_LOCKED`, `MADV_FREE` | VMA_READ_LOCK | ํ์ด์ง ํ
์ด๋ธ ์์ , ๋จ์ผ VMA๋ง ๊ฐ๋ฅ |
| `MADV_GUARD_INSTALL`, `MADV_GUARD_REMOVE` | VMA_READ_LOCK | guard marker ์ค์น/ํด์ |
| `MADV_WILLNEED`, `MADV_COLD`, `MADV_PAGEOUT` | MMAP_READ_LOCK | walk_page_range ์ฌ์ฉ |
| `MADV_REMOVE` | MMAP_READ_LOCK | mmap_lock ํด์ ํ fallocate ํธ์ถ |
| `MADV_COLLAPSE` | MMAP_READ_LOCK | THP ๋๊ธฐ ๋ณํฉ |
| `MADV_POPULATE_READ`, `MADV_POPULATE_WRITE` | MMAP_READ_LOCK | faultin_page_range ์ฌ์ฉ |
| `MADV_NORMAL/SEQUENTIAL/RANDOM/DONTFORK/DOFORK` | MMAP_WRITE_LOCK | vm_flags ๋ณ๊ฒฝ ํ์ |
| `MADV_WIPEONFORK/KEEPONFORK/DONTDUMP/DODUMP` | MMAP_WRITE_LOCK | vm_flags ๋ณ๊ฒฝ ํ์ |
| `MADV_MERGEABLE/UNMERGEABLE` | MMAP_WRITE_LOCK | KSM ์ค์ ๋ณ๊ฒฝ |
| `MADV_HUGEPAGE/NOHUGEPAGE` | MMAP_WRITE_LOCK | THP ์ค์ ๋ณ๊ฒฝ |
| `MADV_HWPOISON`, `MADV_SOFT_OFFLINE` | NO_LOCK | ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ ์ฃผ์
, ์์ฒด ์ฒ๋ฆฌ |
MADV_DONTNEED vs MADV_FREE ๋์ ๋น๊ต
| ํญ๋ชฉ | MADV_DONTNEED | MADV_FREE |
| ํ์ด์ง ํด์ ์์ | ์ฆ์ (zap_page_range) | ์ง์ฐ (๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ ์) |
| PTE ์ฒ๋ฆฌ | ํ์ด์ง ํ
์ด๋ธ ์์ ํด๋ฆฌ์ด | lazyfree ๋งํน๋ง |
| dirty ํ์ด์ง | ๋๋กญ (๋ณต๊ตฌ ๋ถ๊ฐ) | ๋๋กญ (๋ณต๊ตฌ ๋ถ๊ฐ) |
| clean ํ์ด์ง | ์ฆ์ ๋ฐํ | free list์ ์ ์ง |
| ์ ์ฉ ๋์ | ๋ชจ๋ VMA (HugeTLB ํฌํจ) | ์ต๋ช
VMA๋ง |
| mmap_lock | VMA_READ_LOCK ํ์ | VMA_READ_LOCK ํ์ |
| userfaultfd | ์ ๊ฑฐ ํ ์ฌ์ค์ | ์ ๊ฑฐ ํ ์ฌ์ค์ |
MADV_COLD vs MADV_PAGEOUT ๋์ ๋น๊ต
| ํญ๋ชฉ | MADV_COLD | MADV_PAGEOUT |
| LRU ๋์ | active โ inactive ์ด๋ | LRU์์ ๊ฒฉ๋ฆฌ โ ์ฆ์ ํ์ |
| ํ์ด์ง ํด์ | ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ ์ ํ์ | ์ฆ์ ํ์ (reclaim_pages) |
| THP ์ฒ๋ฆฌ | split ์๋ ํ deactivation | split ์๋ ํ LRU ๊ฒฉ๋ฆฌ |
| ํ์ผ ๋งคํ | ๊ฑด๋๋ (can_do_file_pageout) | ์ฐ๊ธฐ ๊ถํ ํ์ธ ํ ์ถ๋ ฅ |
| ์ ์ฉ ๋ถ๊ฐ | VM_LOCKED, VM_PFNMAP, VM_HUGEPAGE | VM_LOCKED, VM_PFNMAP, VM_HUGEPAGE |
process_madvise ์๊ฒฉ ์ ์ฉ ๊ฐ๋ฅ behavior
| behavior | ์๊ฒฉ ์ ์ฉ | ์ค๋ช
|
| `MADV_COLD` | O | ํ์ด์ง ๋นํ์ฑํ |
| `MADV_PAGEOUT` | O | ํ์ด์ง ์ฆ์ ํ์ |
| `MADV_WILLNEED` | O | readahead ํธ๋ฆฌ๊ฑฐ |
| `MADV_COLLAPSE` | O | THP ๋๊ธฐ ๋ณํฉ |
| ๊ทธ ์ธ | X | CAP_SYS_NICE ํ์ + ๋นํ๊ดด์ behavior๋ง ํ์ฉ |
MADV_* ์ ์ฒด ๋ชฉ๋ก
| ์์ | ๊ฐ | ์ค๋ช
| VMA ๋ณ๊ฒฝ |
| `MADV_NORMAL` | 0 | ๊ธฐ๋ณธ readahead | VM_SEQ_READ, VM_RAND_READ ํด์ |
| `MADV_RANDOM` | 1 | ์ต์ readahead | VM_RAND_READ ์ค์ |
| `MADV_SEQUENTIAL` | 2 | ๊ณต๊ฒฉ์ readahead | VM_SEQ_READ ์ค์ |
| `MADV_WILLNEED` | 3 | readahead ํธ๋ฆฌ๊ฑฐ | ์์ |
| `MADV_DONTNEED` | 4 | ์ฆ์ ํ์ด์ง ํด์ | ์์ |
| `MADV_FREE` | 8 | lazyfree ๋งํน | ์์ |
| `MADV_REMOVE` | 9 | ํ์ผ hole punching | ์์ |
| `MADV_DONTFORK` | 10 | fork ์ ๋ณต์ ์ ์ธ | VM_DONTCOPY ์ค์ |
| `MADV_DOFORK` | 11 | fork ์ ๋ณต์ ํฌํจ | VM_DONTCOPY ํด์ |
| `MADV_MERGEABLE` | 12 | KSM ๋ณํฉ ๋์ | VM_MERGEABLE ์ค์ |
| `MADV_UNMERGEABLE` | 13 | KSM ๋ณํฉ ์ ์ธ | VM_MERGEABLE ํด์ |
| `MADV_HUGEPAGE` | 14 | THP ๋์ | VM_HUGEPAGE ์ค์ |
| `MADV_NOHUGEPAGE` | 15 | THP ์ ์ธ | VM_NOHUGEPAGE ์ค์ |
| `MADV_DONTDUMP` | 16 | core dump ์ ์ธ | VM_DONTDUMP ์ค์ |
| `MADV_DODUMP` | 17 | core dump ํฌํจ | VM_DONTDUMP ํด์ |
| `MADV_WIPEONFORK` | 18 | fork ์ ์์ zero-fill | VM_WIPEONFORK ์ค์ |
| `MADV_KEEPONFORK` | 19 | fork ์ ๋ฐ์ดํฐ ์ ์ง | VM_WIPEONFORK ํด์ |
| `MADV_COLD` | 20 | ํ์ด์ง ๋นํ์ฑํ | ์์ |
| `MADV_PAGEOUT` | 21 | ์ฆ์ ์ค์์์ | ์์ |
| `MADV_POPULATE_READ` | 22 | ์ฝ๊ธฐ fault ์ฌ์ ์์ฑ | ์์ |
| `MADV_POPULATE_WRITE` | 23 | ์ฐ๊ธฐ fault ์ฌ์ ์์ฑ | ์์ |
| `MADV_DONTNEED_LOCKED` | 24 | locked ํ์ด์ง ํฌํจ ํด์ | ์์ |
| `MADV_COLLAPSE` | 25 | THP ๋๊ธฐ ๋ณํฉ | ์์ |
| `MADV_SOFT_OFFLINE` | 101 | ์ํํธ ์คํ๋ผ์ธ | ์์ |
| `MADV_HWPOISON` | 100 | ํ๋์จ์ด ์ค๋ฅ ์ฃผ์
| ์์ |
| `MADV_GUARD_INSTALL` | 102 | ์ ๊ทผ ์ fatal signal | guard PTE ๋ง์ปค |
| `MADV_GUARD_REMOVE` | 103 | guard ํด์ | guard PTE ํด๋ฆฌ์ด |
๋ค์ด์ด๊ทธ๋จ
๊ด๋ จ ๋ฌธ์
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ฐ์
VMA / mmap
ํ์ด์ง ํ์
process_vm_readv/writev
Swap / zswap
Huge Pages / THP
KSM
Sealing (mseal)
mlock / munlock
mprotect
mremap