https://dvdhrm.wordpress.com/2014/06/10/memfd_create2/
In teoria, potresti ottenere [memfd_create()
] comportamento senza introdurre nuove syscall, come questo:
int fd = open("/tmp", O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
(Nota, per garantire in modo più portabile un tmpfs qui, possiamo usare “/dev/shm
” invece di “/tmp
“).
Pertanto, la domanda più importante è perché diavolo abbiamo bisogno di una terza via?
[…]
- La memoria di backup viene contabilizzata nel processo che possiede il file e non è soggetta a quote di montaggio.
^ Ho ragione nel pensare che la prima parte di questa frase non sia affidabile?
Il codice memfd_create() è letteralmente implementato come un "file non collegato che vive in [a] tmpfs che deve essere interno al kernel". Tracciando il codice, capisco che differisca nel non implementare i controlli LSM, inoltre i memfd sono creati per supportare i "sigilli", come spiega il post del blog. Tuttavia, sono estremamente scettico sul fatto che i memfd siano contabili in linea di principio diversamente da un tmpfile.
In particolare, quando l'OOM-killer bussa, non penso che spiegherà la memoria detenuta da memfds. Questo potrebbe ammontare fino al 50% della RAM - il valore dell'opzione size=per tmpfs. Il kernel non imposta un valore diverso per il tmpfs interno, quindi utilizzerà la dimensione predefinita del 50%.
Quindi penso che in genere possiamo aspettarci che i processi che contengono un grande memfd, ma nessun'altra allocazione di memoria significativa, non vengano uccisi dall'OOM. È corretto?
Risposta accettata:
Basandosi sulla risposta di @danblack:
La decisione si basa su oom_kill_process()
(ripulito un po'):
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)
Che dipende da oom_badness()
per trovare il miglior candidato:
child_points = oom_badness(child,
oc->memcg, oc->nodemask, oc->totalpages);
oom_badness()
fa:
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)
Dove:
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)
Quindi sembra che conteggi le pagine anonime, che è ciò che è memfd_create()
utilizza.