¿Es incorrecto pensar que los "memfd" se tienen en cuenta "para el proceso que posee el archivo"?

15

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

Teóricamente, podría lograr un memfd_create()comportamiento [ ] sin introducir nuevas llamadas al sistema, como esta:

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

(Tenga en cuenta que para garantizar de forma más portátil un tmpfs aquí, podemos usar " /dev/shm" en lugar de " /tmp").

Por lo tanto, la pregunta más importante es ¿por qué demonios necesitamos una tercera vía?

[...]

  • La memoria de respaldo se contabiliza en el proceso que posee el archivo y no está sujeto a cuotas de montaje.

^ ¿Tengo razón al pensar que no se puede confiar en la primera parte de esta oración?

El código memfd_create () se implementa literalmente como un " archivo no vinculado que vive en [a] tmpfs que debe ser interno del núcleo ". Rastreando el código, entiendo que difiere en no implementar comprobaciones de LSM, también se crean memorias para soportar "sellos", como explica la publicación del blog. Sin embargo, soy extremadamente escéptico de que los memfds se consideren de manera diferente a un archivo tmp en principio.

Específicamente, cuando el OOM-killer llega a tocar, no creo que tenga en cuenta la memoria que tienen los memfds. Esto podría sumar hasta un 50% de RAM, el valor de la opción size = para tmpfs . El kernel no establece un valor diferente para los tmpfs internos, por lo que usaría el tamaño predeterminado del 50%.

Por lo tanto, creo que generalmente podemos esperar que los procesos que contienen una gran memoria, pero no otras asignaciones de memoria significativas, no sean eliminados por OOM. ¿Es eso correcto?

sourcejedi
fuente
2
En cuanto a los puntajes de OOM, parece reducirse a la función kernel oom_badness . Entonces sospecho que si memfd_create no aparece en un / proc / {pid} / map, entonces no se cuenta. Entonces, la respuesta general es que podrían ser eliminados, pero no tendrán una gran puntuación debido al uso de memfd_create. La memoria para el fd se puede compartir entre procesos ya que múltiples procesos pueden heredar / enviarse, el mismo fd.
danblack

Respuestas:

1

Sobre la base de la respuesta de @ danblack:

La decisión se basa en oom_kill_process()(limpiado un poco):

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 )

De lo que depende oom_badness()encontrar el mejor candidato:

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

oom_badness() hace:

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 )

Dónde:

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 )

Entonces parece que cuenta páginas anónimas, que es lo que memfd_create()usa.

V13
fuente