É errado pensar em "memfd" s como responsável "pelo processo que possui o arquivo"?

15

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

Teoricamente, você poderia obter um memfd_create()comportamento [ ] sem introduzir novos syscalls, como este:

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

(Observe, para garantir mais portabilidade um tmpfs aqui, podemos usar " /dev/shm" em vez de " /tmp").

Portanto, a pergunta mais importante é por que diabos precisamos de uma terceira via?

[...]

  • A memória de suporte é contabilizada no processo que possui o arquivo e não está sujeita a cotas de montagem.

^ Estou certo ao pensar que a primeira parte desta frase não pode ser invocada?

O código memfd_create () é literalmente implementado como um " arquivo desvinculado que vive em [a] tmpfs, que deve ser interno ao kernel ". Ao rastrear o código, entendo que ele difere em não implementar verificações de LSM, também são criados memfds para oferecer suporte a "selos", como a postagem do blog continua explicando. No entanto, sou extremamente cético quanto ao fato de os memfds serem contabilizados de maneira diferente a um arquivo tmp em princípio.

Especificamente, quando o assassino do OOM bate à porta, acho que não será responsável pela memória mantida pelos memfds. Isso pode totalizar até 50% da RAM - o valor da opção size = para tmpfs . O kernel não define um valor diferente para os tmpfs internos, portanto, usaria o tamanho padrão de 50%.

Portanto, acho que geralmente podemos esperar que processos que contenham um grande memfd, mas nenhuma outra alocação significativa de memória, sejam eliminados pelo OOM. Isso está correto?

sourcejedi
fonte
2
No que diz respeito às pontuações do OOM, parece se resumir à função oom_badness do kernel . Portanto, suspeito que se o memfd_create não aparecer em um mapa / proc / {pid} / /, não será contabilizado. Portanto, a resposta geral é que eles podem ser mortos, mas não terão uma pontuação grande devido ao uso do memfd_create. A memória para o fd pode ser compartilhada entre processos, pois vários processos podem herdar / ser enviados, o mesmo fd.
Danblack 16/09/19

Respostas:

1

Com base na resposta de @ danblack:

A decisão é baseada oom_kill_process()(limpa um pouco):

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 )

Depende oom_badness()de encontrar o melhor candidato:

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

oom_badness() faz:

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 )

Onde:

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 )

Portanto, parece que conta páginas anônimas, que é o que memfd_create()usa.

V13
fonte