Я новичок в Linux, и меня всегда смущала разница между пространством ядра и пространством пользователя. В настоящее время я изучаю управление памятью и хотел бы знать, принадлежит ли виртуальный адрес страницы пользовательского процесса пространству пользователя или пространству ядра при подкачке или выходе?
(как в 64-битном Linux
Диапазон виртуальных адресов состояния пользователя: 0x0000000 000000-0x00007FFFFFFFFFFFF
Диапазон виртуальных адресов состояния ядра: 0xFFFF8000000000-0xFFFFFFFFFFFFFFFFFFFF)
Linux-6.5.1/мм/memory.c
mm_account_fault()
if (major) {
struct major_page_fault_hash_entry *temp = NULL;
unsigned long pfn = virt_to_pfn(address);
printk("[%lu][i][%lu]", pfn, address);
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
}
Linux-6.5.1/mm/swap_state.c
bool add_to_swap(struct folio *folio)
long pages_number = folio_nr_pages(folio);
unsigned long start_pfn = folio_pfn(folio);
for (int i = 0; i < pages_number; i++) {
struct page *current_page = pfn_to_page(start_pfn + i);
unsigned long current_virt_addr = (unsigned long)page_to_virt(current_page);
printk("[%lu][o][%lu]\n",start_pfn + i, current_virt_addr);
}
Как вы отметили, они определяются только диапазонами адресов. Поскольку виртуальный адрес не меняется при его замене или удалении, как это может повлиять на то, к какому пространству он принадлежит?
@Barmar Я не имел в виду изменение виртуального адреса, вызванное перестановкой страниц. Вы имеете в виду, что если виртуальный адрес полученной страницы принадлежит пространству пользователя или пространству ядра, то страница уже определена при выделении? Изменяя ядро, виртуальный адрес страницы, которую я получаю, находится в пространстве ядра, поэтому я не совсем понимаю, что виртуальный адрес страницы процесса пользовательского режима находится в пространстве ядра.
Я не уверен, что вы имеете в виду. Виртуальный адрес не меняется при замене страницы. Я думаю, вы, возможно, неправильно понимаете то, что видите в модификации ядра.
@Barmar Результат анализа, который я получил, заключается в том, что виртуальный адрес выгруженной страницы находится в пространстве ядра, а виртуальный адрес выгруженной страницы находится в пространстве пользователя. Связано ли это с распределением страниц операционной системы или с настройками программы в пользовательском режиме? Большое спасибо за объяснение!
Вам придется показать код, который вы используете, чтобы определить это.
@Barmar Я уже отредактировал контент
Вы печатаете виртуальный адрес пользователя (и PFN, на который он указывает) в случае ошибки, а также виртуальный адрес ядра (и PFN, на который он указывает) в add_to_swap()
. Сравнивать эти две вещи не имеет особого смысла.
Страница физической памяти в любой момент может иметь любое количество виртуальных адресов, указывающих на нее, как в ядре, так и в пользовательском пространстве. Более того, страницу можно перемещать в физической памяти, а ее PFN может меняться со временем. Вытеснение страницы означает только то, что биты ее записи в таблице страниц будут обновлены, чтобы указать, что страница заменена, чтобы ее можно было правильно заменить при следующей ошибке страницы. Никакого изменения существующих виртуальных адресов пользователей не произойдет и не может произойти.
Моя цель при сборе этих данных — проверить, не менялась ли одна и та же страница несколько раз во время пользовательского процесса.
Вы сможете сделать это из пользовательского пространства через /proc/[pid]/pagemap
. См. документацию здесь. В частности, бит 62 сообщает вам, заменена страница или нет, поэтому, если вы можете запрашивать этот бит достаточно часто, вы можете получить нужную информацию.
Спасибо за объяснение! Моя цель при сборе этих данных — проверить, не менялась ли одна и та же страница несколько раз во время пользовательского процесса, но теперь я обнаружил, что PFN не исправлен. А как насчет виртуальных адресов? Есть ли у вас хорошие идеи, которые могут помочь мне достичь моих целей?
Находится ли адрес в пространстве пользователя или ядра, со временем не меняется. Перестановка входов/выходов на это не влияет.