Valor OOM Killer sempre um a menos que o definido

Valor OOM Killer sempre um a menos que o definido

Estou tentando definir o oom_adjvalor para o eliminador de falta de memória e, cada vez que faço isso (independentemente do processo), recebo exatamente um a menos do que defini (pelo menos para números inteiros positivos. Não tentei números inteiros negativos desde que eu deseja que esses processos sejam eliminados primeiro pelo OOM Killer).

[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 ~]# 

Esse é o comportamento esperado? Se não, por que isso está acontecendo?

Responder1

oom_adjestá obsoleto e é fornecido apenas para fins legados. Internamente o Linux usa oom_score_adjo que tem um alcance maior: oom_adjvai até 15 enquanto oom_score_adjvai até 1000.

Sempre que você escreve para oom_adj(digamos 9), o kernel faz isso:

oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;

e armazena isso em oom_score_adj. OOM_SCORE_ADJ_MAXé 1000 e OOM_DISABLEé -17.

Então, para 9 você obterá oom_adj=(9 * 1000) / 17 ~= 529.411e, como esses valores são inteiros, oom_score_adjconterá 529.

Agora, quando você ler oom_adjo kernel, fará isso:

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

Então, para 529 você obterá: oom_adj = (529 * 17) / 1000 = 8.993e como o kernel usa números inteiros e aritmética de números inteiros, isso se tornará 8.

Então aí... você escreve 9 e obtém 8 por causa da aritmética de ponto fixo/inteiro.

informação relacionada