mmap()함수를 정리하며 VA도 함께 이해하는 게 목표이다.
user space의 virtual memory에 file 또는 anon 매핑을 요청하는 함수이다.
이렇게만 말하면 다소 추상적으로 느껴져 구체적인 설명을 하자면,
mmap() 호출은 file descriptor가 가리키는 객체를 파일에서 offset 바이트 지점을 기준으로 len 바이트만큼 메모리에 mapping하도록 커널에 요청한다.
mapping할 주소를 지정하고자 할 경우 address를 argument로 넘기면 된다. 접근 권한은 port에 지정하고, 추가적인 동작 방식은 flags에 지정한다.
#include <sys/mman.h>
void * mmap (void *addr, size_t len, int port, int flags, int fd, off_t offset);
return 값은 mapping이 시작하는 실제 메모리 주소(?)이다.
addr
커널에게 파일을 어디에 mapping하면 좋을지 제안하는 값 (보통 0 사 용) (0은 제안하지 않음을 의미하는가?)
len
mapping시킬 메모리 영역의 길이 (파일의 크기라 생각하면 되겠다.)
페이지 크기 단위여야 한다.
prot
mapping시 원하는 메모리 보호 정책 (읽기 전용으로 열고자 한다면 PORT_WRITE를 지정하면 안 된다.)
1) PORT_READ: 읽기 가능한 페이지
2) PORT_WRITE: 쓰기 가능한 페이지
3) PORT_EXEX: 실행 가능한 페이지
4) PORT_NONE: 접근할 수 없는 페이지
flags
mapping 유형과 동작 구성 요소
1) MAPFIXED: addr과 len 매개변수가 기존 mapping과 겹칠 경우, 중첩 페이지를 버리고 새 mapping으로 대체. (권장하지 않음) (버린다는 것은, mapping table 상에서 해당 PTE를 제거한다는 뜻?)_
2) MAP_SHARED: 동일 파일을 mapping한 모든 프로세스들이 공유. 객체 접근에 대한 동기화를 위해 msync, munmap을 사용.
3) MAP_PRIVATE: mapping을 공유하지 않는다. 파일은 쓰기 후 복사로 mapping되며 변경된 메모리 속성은 실제 파일에는 반영되지 않는다.
fd
file descriptor
offset
mapping할 때 len의 시작점을 지정
즉, mmap()을 사용하면 file을 process의 virtual memory에 매핑할 수 있다. 이렇게 매핑한 데이터에 파일 입출력 함수를 쓰지 않고(즉, buffer를 거치지 않고) 접근할 수 있다.
(file을 대상이라 한다면 file의 크기 만큼의 virtual space가 file에게 할당되고, file의 physical address와 virtual address가 mapping table에 로드된다는 건가?)
You opened the file in read-only mode. Then you attempted to mmap part of it in read/write mode with MAP_SHARED set. In this context MAP_SHARED implies that if you write to the mmap'd region your changes will be committed back to the mapped file itself. You can't do this because you opened the file in read-only mode.
MAP_PRIVATE works because writes to the mmap'd region are not committed back to the original file. When you write to the region the pages that were written to are copied to a different region of memory, possibly backed by swap space.
mmap()으로 만들어진 mapping을 제거하기 위한 시스템 호출
#include <sys/mman.h>
int * munmap(void * addr, size_t len);
return 값은 성공했을 때 0, 실패했을 때 -1
munmap() 호출은 addr에서 시작하는 프로세스 주소 공간에 위치한 페이지를 포함하는 모든 mapping을 제거한다. 이 영역은 len 바이트 만큼 계속해서 이어져야 하며, 페이지에 정렬되어 있어야 한다.
references: [1] https://m.blog.naver.com/PostView.nhn?blogId=sysganda&logNo=30173573554&proxyReferer=https:%2F%2Fwww.google.com%2F [2] https://mintnlatte.tistory.com/357 [3] https://hololo-kumo.tistory.com/96 [4] https://m.blog.naver.com/PostView.nhn?blogId=bl2019&logNo=10187348331&proxyReferer=https:%2F%2Fwww.google.com%2F [5] https://jhkim3624.tistory.com/58
궁금하던 게 [5] 에 가장 잘 설명되어 있다.
이해하기 쉽네요 감사합니다 :)