https://dvdhrm.wordpress.com/2014/06/10/memfd_create2/
理論的には、次のように、新しいシステムコールを導入することなく、[
memfd_create()
]の動作を実現できます。
int fd = open("/tmp", O_RDWR | O_TMPFILE | O_EXCL, S_IRWXU);
(ここで、tmpfsをより移植性の高い形で保証するために、「/dev/shm
" の代わりに "/tmp
")。
したがって、最も重要な質問は、なぜ地獄に第三の方法が必要なのかということです。
[...]
- バッキングメモリは、ファイルを所有するプロセスに割り当てられ、マウントクォータの対象ではありません。
^この文の最初の部分は信頼できないと思いますか?
memfd_create()コード は、文字通り " [a] tmpfsに存在するリンクされていないファイルであり、カーネル内部である必要があります "として実装されます。コードを追跡すると、LSMチェックを実装しない点が異なることを理解しています。また、ブログポストで説明されているように、「シール」をサポートするためにmemfdsが作成されます。ただし、memfdsがaccountedで、原則としてtmpfileとは異なっていることに非常に懐疑的です。
具体的には、 OOM-killer がノックする場合、memfdsが保持するメモリの原因とはなりません。これは、RAM-tmpfsの size =オプションの値 の最大50%になります。カーネルは内部tmpfsに別の値を設定しません。したがって、デフォルトサイズの50%を使用します。
したがって、大規模なmemfdを保持しているが、他の重要なメモリ割り当てが存在しないプロセスは、OOMで強制終了されないことが一般的に期待できると思います。あれは正しいですか?
@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#L2 )
どこ:
_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()
が使用する匿名ページをカウントしているように見えます。