OOM Killer 값은 항상 설정된 값보다 1 작습니다.

OOM Killer 값은 항상 설정된 값보다 1 작습니다.

메모리 부족 킬러에 대한 값 을 설정하려고 하는데 oom_adj프로세스에 관계없이 그렇게 할 때마다 내가 설정한 것보다 정확히 1만큼 적은 값을 돌려받습니다(적어도 양의 정수의 경우). 이후로 음의 정수를 시도한 적이 없습니다. 먼저 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 ~]# 

이것이 예상된 동작입니까? 그렇지 않다면 왜 이런 일이 발생합니까?

답변1

oom_adj더 이상 사용되지 않으며 레거시 목적으로만 제공됩니다. 내부적으로 Linux는 oom_score_adj더 넓은 범위를 사용합니다. 최대 oom_adj15까지 올라가고 oom_score_adj최대 1000까지 올라갑니다.

oom_adj(9라고 가정하자) 에 쓸 때마다 커널은 다음을 수행합니다.

oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;

그리고 그것을 에 저장합니다 oom_score_adj. OOM_SCORE_ADJ_MAX1000이고 OOM_DISABLE-17입니다.

따라서 9의 경우 oom_adj=(9 * 1000) / 17 ~= 529.411이 값은 정수이므로 oom_score_adj529를 얻게 됩니다.

oom_adj이제 커널을 읽으면 다음과 같은 작업이 수행됩니다.

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

따라서 529의 경우 다음을 얻게 됩니다. oom_adj = (529 * 17) / 1000 = 8.993커널이 정수와 정수 산술을 사용하므로 이는 8이 됩니다.

그래서... 9를 쓰고 고정 소수점/정수 연산 때문에 8을 얻습니다.

관련 정보