2012-02-03 2 views
6

mmap()을 사용하여 가상 메모리를 조작하려고합니다. 나는 기억의 영역을 확보하고 저지하기를 원한다. 이 코드를 테스트했습니다 :크기가 큰 mmap() 호출이 실패하지 않는 이유는 무엇입니까?

const unsigned long gygabyte = 1024 * 1024 * 1024; 
const unsigned long gygabyteCount = 2; 
const unsigned long maxCapacity = gygabyteCount * gygabyte; 

int main() 
{ 
    char* pMemory; 

    pMemory = (char*)mmap(NULL, maxCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
    if (mprotect(pMemory, maxCapacity, PROT_READ | PROT_WRITE) != 0) 
    { 
     cout << "Memory Allocation has failed" << endl; 
    } 
    usleep(-1); 

    return 0; 
} 

터미널에서 내 프로그램 (예 : 6)을 여러 번 실행했습니다. 저는 "메모리 할당이 실패했습니다"라는 것을 전혀 보지 못했습니다. 64 비트 Ubuntu에서 4GB RAM을 사용하고 있습니다. 아무도 이것에 대해 뭔가를 말해 줄 수 있습니까?

+1

메모리 오버 커밋 정보 – PlasmaHH

+0

게시 한 코드가 아무 것도 저지하지 않습니다. 해당 메모리 영역을 살펴 봅니다. – Mat

답변

11

mmap이 영역을가집니다 : 전체 지역이 플래그를 통과하는 mmap를 호출시 할 수 있기 때문에

특정 경우에는, mprotect에 별도의 전화가 필요하지 않습니다 프로세스의 가상 주소 공간을 사용하지만 실제 RAM을 즉시 할당하지는 않습니다. 따라서 64 비트 플랫폼에서 방대한 양의 실패를 예약 할 수 있습니다 (실패 여부를 확인해야하지만 예제 코드는 그렇지 않습니다). RAM의 물리적 페이지는 나중에 메모리에 액세스 할 때 할당됩니다.

mprotect은 예약 된 메모리의 읽기/쓰기 액세스 만 변경합니다. RAM에 상주하지도 않습니다. PROT_NONE 대신 PROT_READ | PROT_WRITEmmap에 전달하고 mprotect으로 전화를 푸면 동일한 효과를 얻을 수 있습니다.

RAM에 직접 메모리가 있어야하는 경우에는 mlock을 사용하십시오. 사용할 수있는 RAM이 충분하지 않으면 실패합니다. 많은 리눅스 플랫폼 (Ubuntu 포함)에는 리소스 제한 (RLIMIT_MEMLOCK)이있어 모든 프로세스가 잠글 수있는 메모리 양을 제한합니다. ulimit -l으로 조정할 수 있습니다.

+0

이렇게 표시해야합니까? 'pMemory = (char *) mmap (NULL, maxCapacity, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); mlock (pMemory, maxCapacity)'mlock()에서 사용 된 메모리가 mmap()에 의해 예약 된 메모리가 아닌 것 같습니다. – antpetr89

+0

나는 1GB를 예약하려고 노력했다. 그러나 mlock()은 -1을 반환했습니다. – antpetr89

+1

@ user1173593 : 나중에 'errno'의 값을 확인하십시오. 자원 제한이 너무 낮다는 것을 나타내는'EPERM' 일 수도 있습니다 ('ulimit -l'으로 설정할 수 있지만 하드 한도가있을 수 있습니다), 또는 충분한 메모리가 없다는 것을 나타내는'ENOMEM' 일 가능성이 있습니다 , 또는 맨 페이지에 문서화 된 기타 오류. –

0

먼저 mmap의 결과를 확인해야합니다. MAP_FAILED을 반환하는 경우 할당이 실패했음을 의미합니다. 커널은 실제로 많은 양의 메모리를 한 번에 할당하지 않지만 블록의 해당 영역에 액세스 할 때 필요에 따라 물리적 또는 스왑 공간을 매핑합니다.

pMemory = mmap(NULL, maxCapacity, 
    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 

if (pMemory == MAP_FAILED) { 
    /* allocation failed */ 
} 
1

mmap은 요청한 메모리 매핑을 준비하는 데 유용하지만 프로그램에 할당하지 않습니다. 커널은 사용자가 액세스 할 때 메모리를 할당하므로 8GB를 동시에 액세스하지 않으면 4GB 메모리에서 8GB를 사용할 수 있습니다 (mmap).

echo "2" > /proc/sys/vm/overcommit_memory 

이 그렇지 않으면 무제한 오버 커밋을 허용하고 끔찍하여 응용 프로그램을 만드는 (리눅스 장난감 OS 때부터) 기존의 기본을 유지 첫째

0

, 당신은 당신이 회계 커밋하고 싶은 리눅스 말할 필요 실제 메모리가 부족할 때 충돌이 발생합니다.

다른 사람들도 말했듯이 mmap의 반환 값을 MAP_FAILED에 대해 확인해야하며 mprotect을 사용할 필요가 없습니다. 먼저 PROT_*의 오른쪽 값을 mmap으로 전달하면됩니다.

관련 문제