Чи неправильно думати про "memfd" s як "процес, який належить файлу"?


15

https://dvdhrm.wordpress.com/2014/06/10/memfd_create2/

Теоретично ви можете досягти [ memfd_create()] поведінки, не вводячи нових системних викликів, наприклад:

int fd = open("/tmp", O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);

(Зверніть увагу, щоб більш портативно гарантувати tmpfs тут, ми можемо використовувати " /dev/shm" замість " /tmp").

Тому найважливіше запитання - чому, до біса, нам потрібен третій шлях?

[...]

  • Резервна пам'ять обчислюється процесом, який належить файлу, і не підлягає квотам кріплення.

^ Чи правильно я думаю, що на першу частину цього речення не можна покластися?

Код memfd_create () буквально реалізований як " від’єднаний файл, що живе в [a] tmpfs, який повинен бути внутрішнім ядром ". Відслідковуючи код, я розумію, що він відрізняється тим, що не застосовує перевірки LSM, також створюються memfds для підтримки "печатки", як пояснюється повідомлення в блозі. Тим НЕ менше, я дуже сумніваюся , що memfds будуть враховуватися по- різному до tmpfile в принципі.

Зокрема, коли вбивця OOM стукає, я не думаю, що це буде враховувати пам'ять, яку зберігають memfds. Це може становити до 50% оперативної пам'яті - значення розміру = варіант для tmpfs . Ядро не встановлює інше значення для внутрішніх tmpfs, тому воно використовує розмір за замовчуванням 50%.

Тому я думаю, що ми, як правило, можемо очікувати, що процеси, які займають велику memfd, але жодне інше значне розподілення пам'яті, не буде знищено OOM. Це правильно?


2
Що стосується балів OOM, то, схоже, зводиться до функції ядра oom_badness . Тому я підозрюю, що якщо memfd_create не відображається в / proc / {pid} / map, то його не враховується. Тож загальна відповідь - їх можна вбити, але вони не матимуть великого балу через використання memfd_create. Пам'ять для fd може бути поділена в різних процесах, оскільки кілька процесів можуть успадковувати / надсилати, той самий fd.
danblack

Відповіді:


1

Спираючись на відповідь @ danblack:

Рішення засноване на oom_kill_process()(трохи очищеному):

for_each_thread(p, t) {
        list_for_each_entry(child, &t->children, sibling) {
                unsigned int child_points;

                child_points = oom_badness(child,
                        oc->memcg, oc->nodemask, oc->totalpages);
                if (child_points > victim_points) {
                        put_task_struct(victim);
                        victim = child;
                        victim_points = child_points;
                        get_task_struct(victim);
                }
        }
}

( https://github.com/torvalds/linux/blob/master/mm/oom_kill.c#L974 )

Від чого залежить oom_badness()знайти найкращого кандидата:

child_points = oom_badness(child,
        oc->memcg, oc->nodemask, oc->totalpages);

oom_badness() робить:

points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) +
        mm_pgtables_bytes(p->mm) / PAGE_SIZE;

( https://github.com/torvalds/linux/blob/master/mm/oom_kill.c#L233 )

Де:

static inline unsigned long get_mm_rss(struct mm_struct *mm)
{
        return get_mm_counter(mm, MM_FILEPAGES) +
                get_mm_counter(mm, MM_ANONPAGES) +
                get_mm_counter(mm, MM_SHMEMPAGES);
}

( https://github.com/torvalds/linux/blob/master/mm/oom_kill.c#L966 )

Так виглядає, що він нараховує анонімні сторінки, що і memfd_create()використовує.

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