2010-08-02 5 views
4

, 그것은 천천히 내 기억을 먹고도 스왑을 사용하여 시작합니다NSMutableData는 어떻게 메모리를 할당합니까? 나는 다음과 같은 코드를 실행하면

long long length = 1024ull * 1024ull * 1024ull * 2ull; // 2 GB 

db = [NSMutableData dataWithLength:length]; 

char *array = [db mutableBytes]; 

for(long long i = 0; i < length - 1; i++) { 
     array[i] = i % 256; 
} 

내가주기에 대한 기억이 전혀 사용되지 않는없이 실행하는 경우 :

long long length = 1024ull * 1024ull * 1024ull * 2ull; 
db = [NSMutableData dataWithLength:length]; 
char *array = [db mutableBytes]; 
/* for(long long i = 0; i < length - 1; i++) { 
     array[i] = i % 256; 
} */ 

나는 단지 NSMutableData가 메모리를 "예약"하고있을 때만 접근 할 수 있다고 결론을 내릴 수있다. 정확히 어떻게 이루어 집니까?

이 작업은 하드웨어 (CPU)를 통해 수행됩니까?

NSMutableData가 "예약 된"메모리에서 메모리 쓰기를 catch 한 다음 "할당"을 수행하는 방법이 있습니까?

[NSMutableData dataWithLength:length]에 대한 호출이 결코 실패 할 수 없다는 의미입니까? 필요한 경우 스왑을 사용하여 메모리 크기를 할당 할 수 있습니까?

실패 할 경우 db 변수는 null이됩니까?

사과의 "NSMutableData 클래스 참조"에서 나는이 주제에 관해 막연한 문장을 보았습니다.

답변

6

이것은 NSMutableData 문제가 아니라 커널/OS 문제입니다. 프로세스가 (큰) 메모리 덩어리를 요청하면 커널은 보통 "ok, 여기 있습니다."라고 말할 것입니다. 그러나 실제로 그것을 사용하는 경우에만 실제로 ("물리적으로") 할당됩니다. 이것은 프로그램이 2GB malloc (여기에서 하듯이)에서 시작한다면 즉시 다른 프로그램을 스왑으로 밀어 낼 것이기 때문에 실제로는 2GB를 사용하지 않을 것이기 때문에 이것은 괜찮습니다.

실제 메모리에 실제로 존재하지 않는 메모리 페이지에 액세스 할 때 커널은 CPU로부터 신호를받습니다. 페이지가 있어야한다면 (2GB짜리 청크 안에 있기 때문에) 스왑을 통해 제자리에 놓이게 될 것이며 통지하지 않을 것입니다. 가상 메모리 내에 주소가 할당되지 않았기 때문에 페이지가 없어야한다면 세그멘테이션 오류 (SIGSEGV 또는 EXC_BAD_ACCESS 종류의 오류)가 발생합니다.

관련 주제 중 하나는 커널이 실제로 사용할 수있는 것보다 많은 메모리를 약속하는 "overcommit (ment)"입니다. 모든 프로세스가 약속 된 메모리를 사용하기 시작하면 심각한 문제가 발생할 수 있습니다. 이는 OS에 따라 다릅니다.

인터넷에 많은 부분이 더 잘 설명되어 있습니다. 나는 당신이 구글에 넣을 용어를 가질 수 있도록 짧은 소개를하고 싶었다. 내가 당신을 확신 - - 동안 만 테스트

편집, 리눅스는 쉽게 나에게 메모리의 4 TB를 약속합니다 그 기계에서 총 디스크 스토리지도 1 TB는 없다. 이 문제를 해결하지 못하면 미션 크리티컬 시스템을 구축 할 때 두통을 일으킬 수 있다고 상상할 수 있습니다.

+1

'overcommit_memory'와'overcommit_ratio'를 설정하여 리눅스 오버 커밋 동작을 변경할 수 있습니다. 특히'overcommit_memory'를 2로 설정하면 스왑 공간 + 실제 메모리의 overcommit_ratio % 만 커밋합니다. –

+0

[overcommit-accounting documentation] (http://www.mjmwired.net/kernel/Documentation/vm/overcommit-accounting)도 참조하십시오. –

+0

리눅스에 대한 흥미로운 점은 malloc이 표면 아래에있는'mmap()'이 과도한 커밋 동작을 허용하는 플래그'MAP_NORESERVE'를 취한다는 것입니다. 그러나 malloc()과 같이 -이 플래그를 지정하지 않으면 여전히 오버 커밋됩니다. – mvds

관련 문제