https://dvdhrm.wordpress.com/2014/06/10/memfd_create2/
Theoretisch könnten Sie [memfd_create()
erreichen ]-Verhalten, ohne neue Systemaufrufe einzuführen, etwa so:
int fd = open("/tmp", O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
(Beachten Sie, um hier einen tmpfs portierbarer zu garantieren, können wir „/dev/shm
verwenden “ statt „/tmp
“).
Daher ist die wichtigste Frage, warum zum Teufel brauchen wir einen dritten Weg?
[…]
- Der Hintergrundspeicher wird dem Prozess zugerechnet, der die Datei besitzt, und unterliegt keinen Einhängequoten.
^ Gehe ich recht in der Annahme, dass auf den ersten Teil dieses Satzes kein Verlass ist?
Der Code memfd_create() ist buchstäblich als „nicht verknüpfte Datei, die in [einem] tmpfs lebt, das Kernel-intern sein muss“ implementiert. Wenn ich den Code nachverfolge, verstehe ich, dass er sich dadurch unterscheidet, dass keine LSM-Prüfungen implementiert werden, außerdem werden memfds erstellt, um „Siegel“ zu unterstützen, wie der Blog-Beitrag weiter erklärt. Ich bin jedoch äußerst skeptisch, dass memfds angerechnet werden prinzipiell anders als eine tmpfile.
Insbesondere wenn der OOM-Killer anklopft, glaube ich nicht, dass er den Speicher von memfds berücksichtigen wird. Dies kann bis zu 50 % des Arbeitsspeichers ausmachen – der Wert der Option size=für tmpfs. Der Kernel setzt keinen anderen Wert für das interne tmpfs, also würde er die Standardgröße von 50 % verwenden.
Ich denke also, dass wir im Allgemeinen erwarten können, dass Prozesse, die einen großen memfd, aber keine anderen signifikanten Speicherzuweisungen enthalten, nicht durch OOM getötet werden. Ist das richtig?
Akzeptierte Antwort:
Aufbauend auf der Antwort von @danblack:
Die Entscheidung basiert auf oom_kill_process()
(etwas aufgeräumt):
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)
Was von oom_badness()
abhängt um den besten Kandidaten zu finden:
child_points = oom_badness(child,
oc->memcg, oc->nodemask, oc->totalpages);
oom_badness()
tut:
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)
Wo:
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)
Es sieht also so aus, als würden anonyme Seiten gezählt, was memfd_create()
ist verwendet.