Неправильно ли думать о «memfd» как о «процессе, которому принадлежит файл»?

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% оперативной памяти - значение параметра size = для tmpfs . Ядро не устанавливает другое значение для внутренних tmpfs, поэтому оно будет использовать размер по умолчанию 50%.

Поэтому я думаю, что в целом мы можем ожидать, что процессы, которые содержат большой memfd, но никакие другие значительные выделения памяти, не будут уничтожены OOM. Это верно?

sourcejedi
источник
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()используется.

V13
источник