Коли вилки процесу копіюють його віртуальну або резидентну пам'ять?


12

Стандартний спосіб створення нових процесів в Linux полягає в тому, що слід пам'яті батьківського процесу копіюється і стає середовищем дочірнього процесу, поки не execvбуде викликано.

Про який слід пам’яті ми говоримо, віртуальну (що вимагає процес) або резидентну (що насправді використовується)?

Мотивація: у мене є пристрій з обмеженим простором підкачки та програма із великою різницею між віртуальною та резидентною пам'яттю. Програма не може розщедритися через брак пам'яті і хотіла б побачити, чи допоможе спроба зменшити розмір віртуального сліду.

Відповіді:


12

У сучасних системах жодна пам'ять насправді не копіюється лише тому, що використовується системний виклик вилки. Це все позначено як прочитане лише в таблиці сторінки таким чином, що при першій спробі записати пастку в код ядра станеться. Лише одного разу перша спроба процесу написання відбудеться копіювання.

Це відомо як копіювання під час запису.

Однак може знадобитися також слідкувати за виділеним адресним простором. Якщо під час ядра копіювання сторінки немає пам’яті або заміни, вона повинна вбити деякий процес, щоб звільнити пам'ять. Це не завжди бажано, тому можна відслідковувати, скільки пам’яті взяло ядро.

Якщо ядро ​​взяло б на себе більше, ніж наявна пам'ять + своп, воно може дати код помилки при спробі виклику вилки. Якщо доступно достатньо, ядро ​​буде зобов’язуватися до повного віртуального розміру з батьків для обох процесів після вилки.


1
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.Так дякую. Це означає, що зменшення віртуального сліду процесу в середовищі з обмеженою пам'яттю (оперативна пам'ять і своп) може вирішити проблему неможливості розщедритися.
TheMeaningfulEngineer

1
@Alan Так. Якщо forkне вдалося, повідомлення про помилку вказує на недостатню кількість пам'яті. Тоді зменшення використання віртуальної пам’яті процесу перед форкінгом може допомогти.
kasperd

5

Не хвилюйтесь, це робить ліниву копію (копіювати на запис). Адреси віртуальної пам'яті обох процесів спочатку вказують на одні і ті ж сторінки, але коли роздвоєний процес намагається змінити його, він фактично робить фізичну копію сторінки (з цього моменту ця сторінка знаходиться у двох місцях вашої оперативної пам’яті).

Будьте обережні, жоден із повідомлених слідів пам’яті насправді не говорить про те, яка частина оперативної пам’яті використовує процес. Через обмін, обмін пам’яттю та інші проблеми з віртуальною пам’яттю, це точно неможливо знати. Деякі частини простору пам’яті є спільними бібліотеками (куди їх рахувати?), Деякі посилаються на пам'ять, яка не є оперативною пам’яттю (інші апаратні пристрої), деякі наразі замінені, деякі ще не скопійовані (копіювати при записі) та так далі. Прочитай це:

https://lwn.net/Articles/642202/


5

Є налаштування ядра

/ proc / sys / vm / overcommit_memory

Цитування з чудової статті :

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

Це стосується як виделок, так і звичайного лоскуса. Тобто, якщо ви встановите його на 0, форк буде копіюватися при записі. Копіювати при написанні означає, що раз додаток роздвоєне, обидві копії поділяться сторінками пам’яті утилітами дочірнього або оригінал починає змінювати пам’ять.

У більшості дистрибутивів я знаю, що перевиконання дорівнює 0. Але якщо встановити його на 2, всі сторінки пам'яті будуть повністю підкріплені реальною пам'яттю, а в деяких випадках під високим тиском пам'яті будуть більш стабільними, але деякі програми (я зіткнувся з gitk), на які покладаються на перевиконання не вдасться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.