Как процесс fork () помечает родительские PTE только для чтения? - PullRequest
3 голосов
/ 23 февраля 2020

Я искал много ресурсов, но не нашел ничего конкретного по этому вопросу:

Я знаю, что в некоторых linux системах системный вызов fork() работает с копированием при записи; то есть родитель и потомок совместно используют одно и то же адресное пространство, но PTE теперь помечен только для чтения , который будет использоваться позже COW. при попытке доступа к странице происходит PAGE_FAULT, и страница копируется в другое место, где ее можно изменить.

Однако я не могу понять, как ОС достигает общих PTE, чтобы пометить их как "читать". Я предположил, что когда происходит системный вызов fork(), ОС преобразует «просмотр страницы» родительской таблицы страниц и помечает их как только для чтения - но я не нахожу подтверждения этому или какой-либо информации относительно процесса.

Кто-нибудь знает, как страницы помечаются как только для чтения? Буду признателен за любую помощь. Спасибо!

1 Ответ

4 голосов
/ 24 февраля 2020

Linux ОС реализует ветвь syscall с итерацией по всем диапазонам памяти (mmap s, стек и куча) родительского процесса. Копирование этих диапазонов (VMA - Области виртуальной памяти в функции copy_page_range (мн. / Память. c), в которых l oop для записей таблицы страниц:

    /*
     * 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);
    }

, где is_cow_mapping будет верно для частных и потенциально доступных для записи страниц ( флаги битовых полей проверяются на совместное использование и биты майруширования и должны иметь только установленный бит майруширования)

#define VM_SHARED   0x00000008
#define VM_MAYWRITE 0x00000020

static inline bool is_cow_mapping(vm_flags_t flags)
{
    return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
}

PUD, PMD и PTE описаны в книгах, таких как https://www.kernel.org/doc/gorman/html/understand/understand006.html и в таких статьях, как LWN 2005: «Объединение четырехуровневых таблиц страниц» .

Как реализация fork вызывает copy_page_range:

  • реализация системного вызова fork ( sys_fork? или syscall_define0 (fork) ) равен do_fork (kernel / fork. c), что вызовет
  • copy_process, который вызовет многие функции copy_ * * , включая
  • copy_mm, который вызывает
  • dup_mm для выделения и заполнения новой структуры mm, где большая часть работы выполняется с помощью
  • dup_mmap (все еще ядро ​​/ ветвь. c), который будет проверять, что было преобразовано и как. (Здесь я не смог получить точный путь к реализации COW, поэтому я использовал поисковую машину Inte rnet с чем-то вроде «fork + COW + dup_mm», чтобы получить подсказки типа [1] или [ 2] или [3] ). После проверки типов mmap есть строка retval = copy_page_range(mm, oldmm, mpnt); для реальной работы.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...