2017-12-02 50 views
0

예를 들면. 여기 + 10 매핑파일에 mmap 할 수 있지만 파일 크기를 초과 할 수있는 이유는 무엇입니까?

fd = ::open ("/test.txt", O_RDONLY, 0); 
struct stat buf; 
fstat(fd, &buf); 
char* addr = (char*)::mmap(NULL, buf.st_size + 10, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0); 

알 수 있습니다. 하지만 여전히 작동합니까?

시스템에 어떤 체크가 적용되지 않는 이유는 무엇입니까? 위험한가요? mmap에의

감사

+0

태그를 편집하십시오. 'c'와'C++ '모두 오도 된 것입니다 – coderredoc

+0

왜 그래야합니까? – Stargateur

+0

@coderredoc mmap()은 c와 C++에서 동일하게 호출 할 수 있습니다. –

답변

2

서명은 다음과 같습니다

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 

은 마이클 케 리스크를 인용하자면 :

길이 인수는 바이트 단위로 매핑의 크기를 지정합니다. 길이가 시스템 페이지 크기 (sysconf (_SC_PAGESIZE)에 의해 반환 됨)의 배수 일 필요는 없지만 커널은이 크기의 단위에 매핑을 생성하므로 길이는 실제로는 반올림됩니다. 다음 페이지 크기의 배수. -

로버트 사랑을 인용 리눅스 프로그래밍 인터페이스 (장 49) :

의 mmap() 시스템 호출 페이지에서 작동합니다. addr 및 offset 매개 변수는 모두 페이지 크기의 경계에 정렬되어야합니다. 즉, 페이지 크기의 정수배 여야합니다. 따라서 매핑은 페이지의 정수배입니다. 호출자가 제공 한 len 매개 변수가 기본 파일 크기가 페이지 크기의 배수가 아니 어서 페이지 경계에 정렬되지 않은 경우 매핑이 다음 전체 페이지로 반올림됩니다. 마지막으로 유효한 바이트와 매핑 끝 사이의이 추가 된 메모리 내부의 바이트는 0으로 채워집니다. 해당 영역에서의 읽기는 모두 0을 리턴합니다. 해당 메모리에 대한 쓰기는 MAP_SHARED로 매핑되는 경우에도 백업 파일에 영향을 미치지 않습니다. 원래 len 바이트 만이 파일에 다시 쓰여집니다. - 리눅스 시스템 프로그래밍 (제 4 장)

+0

이것은 mmap 메모리가 항상 요청 된 것보다 클 수 있음을 보여줍니다. 그러나 mmap 메모리가 파일을 백업하는 파일보다 엄격하게 큰 경우, 예를 들어 파일 크기를 초과하는 메모리 액세스가 오류를 만드는 경우 OP의 질문이 오히려 발생합니다. 자동으로 파일을 0으로 확장합니까? 기타 –

+0

안녕하겐, 편집 된 답변을 참조하십시오. – nachiketkulk

1

귀하의 시스템에 Linux가 실행되고 있다고 가정합니다. intro(2)을 반드시 읽으십시오.

우리는 mmap(2) 파일 크기보다 우리가 아니라 페이지 크기의 정확한 배수 만 파일 (일반적으로 4KB이다, 아마 1Mbytes은 PAGESIZEsysconf(3) 참조) 할 수 있습니다 경우 때문에 메모리 매핑 될 수 있습니다. 그럴 경우 메모리 매핑 파일은별로 유용하지 않습니다. 또한 mmap -ed 파일의 크기는 시간에 따라 다를 수 있습니다 (다른 프로세스 write(2) - 첨부 및 추가, ftruncate(2) 등의 호출 ...). 따라서 kernel은 해당 파일을 필요로하거나 적용하지 않는 것이 좋습니다. 변하지 않는다.

신중 mmap(2)의 문서를 읽고, 그것을 말한다 :

파일은 페이지 크기의 배수에 매핑됩니다. 페이지 크기의 배수가 아닌 인 파일의 경우 이 매핑되면 나머지 메모리는 0으로 설정되고 해당 영역에 대한 쓰기는 파일에 기록되지 않습니다.

실패 할 수

mmap (물론 커널이 어떤 당신이 상상하는 것보다 아마도 더 많은 검사를하고있다, 그래서), 그래서 당신의 코드가를 확인해야합니다, 예를 들어, 과에 따라 :

if ((void*)addr == MAP_FAILED) 
     { perror("mmap"); exit(EXIT_FAILURE); }; 

BTW, 당신의 문제는 (다른 운영 체제가 memory mapped files를 제공하지 않을 수 있습니다, 또는 그들에 다른 제약을 둘 수 있었다) C++에만있는 것이 아니라 POSIX 또는 리눅스 고유의 것입니다.

메모리 매핑은 매우 일반적입니다. mmapexecve(2) 시간에 사용됩니다. 중 일부는 process이며, using/proc/ (proc(5) 참조)과 cat /proc/self/mapscat /proc/$$/maps (터미널에서 시도)을 이해할 수 있습니다. 그리고 mmap이 매우 자주 사용됩니다 : malloc(3)operator new, dlopen(3), ld-linux(8) 동적 링크 된 공유 라이브러리.

Linux 또는 POSIX 프로그래밍에 대한 책 (예 : Advanced Linux Programming, 자유롭게 다운로드 할 수있는 것 또는 최신 버전)과 Operating Systems: Three Easy Pieces도 읽어보십시오.