El valor de OOM Killer siempre es uno menos que el establecido

El valor de OOM Killer siempre es uno menos que el establecido

Estoy tratando de establecer el oom_adjvalor para el asesino de falta de memoria, y cada vez que lo hago (independientemente del proceso) obtengo exactamente uno menos de lo que configuré (al menos para números enteros positivos. No he probado números enteros negativos desde que desea que OOM Killer elimine estos procesos primero).

[root@server ~]# echo 10 > /proc/12581/oom_adj
[root@server ~]# cat /proc/12581/oom_adj
9
[root@server ~]# echo 9 > /proc/12581/oom_adj
[root@server ~]# cat /proc/12581/oom_adj
8
[root@server ~]# echo 8 > /proc/12581/oom_adj
[root@server ~]# cat /proc/12581/oom_adj
7
[root@server ~]# echo 7 > /proc/12581/oom_adj
[root@server ~]# cat /proc/12581/oom_adj
6
[root@server ~]# 

¿Es este el comportamiento esperado? Si no, ¿por qué sucede esto?

Respuesta1

oom_adjestá en desuso y se proporciona únicamente para fines heredados. Internamente usa Linux oom_score_adjel que tiene mayor rango: oom_adjsube hasta 15 mientras que oom_score_adjsube hasta 1000.

Cada vez que escribes en oom_adj(digamos 9), el kernel hace esto:

oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;

y lo almacena en oom_score_adj. OOM_SCORE_ADJ_MAXes 1000 y OOM_DISABLEes -17.

Entonces, para 9 obtendrás oom_adj=(9 * 1000) / 17 ~= 529.411y, dado que estos valores son números enteros, oom_score_adjcontendrá 529.

Ahora cuando leas oom_adjel kernel hará esto:

oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) / OOM_SCORE_ADJ_MAX;

Entonces, para 529 obtendrás: oom_adj = (529 * 17) / 1000 = 8.993y dado que el núcleo usa números enteros y aritmética de enteros, esto se convertirá en 8.

Entonces... escribes 9 y obtienes 8 debido a la aritmética de punto fijo/enteros.

información relacionada