https://dvdhrm.wordpress.com/2014/06/10/memfd_create2/
理論的には、[
memfd_create()
を実現できます。 ]次のような新しいsyscallを導入しない動作:
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-killerがノックするとき、memfdsが保持するメモリを考慮しないと思います。これは合計でRAMの最大50%になる可能性があります–tmpfsのsize=オプションの値です。カーネルは内部tmpfsに別の値を設定しないため、デフォルトのサイズである50%を使用します。
したがって、一般的に、大きなmemfdを保持するプロセスは期待できますが、他の重要なメモリ割り当てはOOM-killされないと思います。それは正しいですか?
承認された回答:
@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()
です。 使用します。