sysctl의 "메모리 누락" 설명

sysctl의 "메모리 누락" 설명

OS X Yosemite에서 다음 코드를 실행했습니다.

unsigned long num_;
sysctl((int[]){CTL_HW, HW_PHYSMEM}, 2, &num_, &len, NULL, 0);
printf("AMT MEM: , %lu\n", num_);

그리고 돌아와140735340871680

이것은 말이 되지 않습니다: (IPython 3에서)

In [3]: mem / (1024 ** 3)
mem / (1024 ** 3)
Out[3]: 131070.0

16GB의 물리적 메모리가 있기 때문입니다. 제목보고 sysctl.h봤는데

#define HW_PHYSMEM   5      /* int: total memory */
#define HW_USERMEM   6      /* int: non-kernel memory */

이제 이것은 정말 말이 되지 않습니다. 통과하면 숫자를 신뢰할 수 있지만 HW_USERMEM구체적으로 총 메모리를 요청했습니다. 무엇을 제공합니까?

제가 Python 코드에서 어리석은 수학 실수를 저질렀나요?

답변1

제가 Python 코드에서 어리석은 수학 실수를 저질렀나요?

실제로 잘못된 것은 C 코드입니다.

코드에 대한 가장 간단한 수정은 다음과 같습니다.

#include <stdio.h>
#include <sys/sysctl.h>

int main(void)
{
    int64_t bytes;
    size_t len = sizeof(bytes);
    sysctl({ CTL_HW, HW_PHYSMEM64 }, 2, &bytes, &len, NULL, 0);
    int megs = bytes / 1024 / 1024;
    printf("AMT MEM: %d MiB\n", megs);
}

대신 이를 사용하는 경우 HW_PHYSMEM바이트 수를 32비트 크기로 가정되는 변수에 저장하기 때문에 RAM이 최대 2GiB인 시스템에서만 작동합니다. 64비트 매개변수를 변경하려면 sysctl이전 버전과의 호환성이 깨지는 것을 방지하기 위해 새로운 값이 필요합니다. 이것이 OpenBSD sysctl(3)매뉴얼 페이지에 HW_PHYSMEM더 이상 사용되지 않는다고 나와 있는 이유입니다.

위의 코드를 일부 변경했습니다. 계산기를 통해 입력하지 않고도 출력을 읽을 수 있도록 C 코드로 일부 수학 작업을 수행하고 있습니다. 또한 명확성 num_을 위해 몇 가지 정수 유형 경고를 수정하고 변수 이름을 변경했습니다 bytes.

이 코드는 일부 BSD에서는 제대로 실행되지만 OS X 또는 FreeBSD에서는 실행되지 않습니다.

OS X 매뉴얼 페이지를 보면 그들이 당신이 사용하기를 원하는 것 같습니다.sysctlbyname(3)대신에. 요세미티에서는 잘 작동합니다.

#include <stdio.h>
#include <sys/sysctl.h>

int main(void)
{
    int64_t bytes;
    size_t len = sizeof(bytes);
    sysctlbyname("hw.memsize", &bytes, &len, NULL, 0);
    int megs = bytes / 1024 / 1024;
    printf("AMT MEM: %d MiB\n", megs);
}

16GiB의 물리적 RAM이 있고 16384MiB가 올바르게 보고됩니다.

그러나 FreeBSD에서 이것을 시도하면 답은 0이 됩니다. 조금만 파보면 hw.physmem그 반대를 원한다는 것을 알 수 있습니다.

다시 한 번 우리는 벽에 부딪혔습니다.저것 sysctlbynameOS X의 값은 당신이 찾은 일종의 가짜 결과를 제공합니다.

따라서 결론적으로 이 모든 것은 시스템에 따라 매우 다르다는 것입니다. 크로스 플랫폼이 필요하다면 많은 #ifdefs.


각주:

  1. 죄송합니다. 아직 2의 거듭제곱을 10억으로 적지 않았습니다. :)

  2. OpenBSD 5.5 및 NetBSD 6.0.1에서 테스트되었습니다.

관련 정보