-
[SW 정글 86일차] mmap()과 read()/write()기타/SW 사관학교 정글 2021. 10. 28. 02:23
오늘은 project3를 마무리짓는 날로 전체적으로 복습하는 시간과 memory management 개념을 강의를 보며 다시 리마인드했다.
그 중에서 mmap()과 read()/write()에 대해 의문을 가졌다.
의문을 가진 점은 두 시스템콜이 비슷한 역할을 하는 것 같은데 정확히 어떠한 차이점이 있는지이다.
read()/write()는 project2 때 구현한 것이지만 그 때에는 완벽히 나의 것으로 만들지 못해 차이점을 바로 알지 못했다.
그래서 조금 더 자료를 찾아보면서 어떠한 차이점이 있는지 알았다.
1. mmap() 과 read()/ write()의 차이점은?
먼저, 3가지의 systemcall이 어떠한 역할을 하는지 알아보자.
Linux manual page에서는 mmap()을 다음과 같이 설명한다.
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
mmap()은 호출한 프로세스의 가상 메모리에 새로운 mapping을 만드는 것이다.
새로운 mmaping의 시작 주소는 인자로 준 addr로 특정된다.
(정확히 addr로 줄 수도 있지만 이미 addr에 page가 할당되었다면 addr을 참고하여 시작 주소를 mapping한다.)
그리고 인자로 준 length를 mapping을 얼마큼의 길이로 할지 특정한다.
file mappig의 contents는 인자로 준 fd로 참조된 file 내의 offset을 시작점으로 하여 length만큼을 이용하여 초기화한다.
(MAP_ANONYMOUS인 경우는 아니다.)
[출처: https://man7.org/linux/man-pages/man2/mmap.2.html]
다음으로 read()와 write()에 대해 알아보자.
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);
read()는 fd로 참조한 file에서 인자로 준 buf를 시작점으로 하여 buffer에 count(세 번째 인자 값) 바이트만큼 읽어들이는 것을 시도하는 것이다.
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);
write()는 fd로 참조한 file에서 인자로 준 buf를 시작점으로 하여 buffer에 count(세 번째 인자 값) 바이트만큼 쓰는 것을 시도하는 것이다.
내가 헷갈린 것은 그냥 mmap()으로 file을 읽어들여서 해당 주소에 가서 write하는 것이 read()와 write()와 같은 역할을 하는 것이지 않을까이다.
일단은 검색을 해봤다.
검색결과는 mmap()과 read()/write() 모두 리눅스의 I/O 접근 방법이다.
그 중 read()/ write()는 traditional한 방법이다.
조금 더 차이점을 알아보기 위해 검색하던 중 아래의 article을 보았다.
read와 mmap의 performance를 비교한 것이다.
여기서 확실히 차이점을 알 수 있었다.
In traditional file I/O involving read, data is copied from the disk to a kernel buffer, then the kernel buffer is copied into the process's heap space for use. In memory-mapped file I/O, data is copied from the disk straight into the process's address space, into the segment where the file is mapped. The file is then accessed by references to memory locations with pointers.
This way, I/O on the file is done without the overhead of handling the data twice; this translates into an improvement in system performance.read는 데이터가 파일이 있는 디스크에서 kernel buffer로 copy되고 데이터가 사용될 때, kernel buffer는 process의 heap 영역에 copy된다.
mmap은 파일이 있는 디스크에서 곧바로 process의 주소 공간(가상메모리)의 file이 map되는 segment로 copy된다.
이렇게 read는 2번의 과정이 이루어져 mmap보다 overhead가 증가하여 peformace측면에서 read가 mmap보다 떨어진다.
2. mmap()의 장점과 단점은?
전통적인 방법인 read()보다 performace측면에서 좋은 시스템콜이라고 알게 되었다.
그러면 mmap()의 장점과 단점은 어떻게 될까?
아래의 블로그 글에서 정보를 얻었다.
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=websearch&logNo=221549751119
mmap의 장점
1) 메모리에 맵핑된 파일을 읽거나 쓰면 read() 나 write() 시스템 콜을 사용할 때 발생하는 불필요한 복사를 방지할 수 있다. 이런 추가적인 복사는 사용자 영역의 버퍼로 데이터를 읽고 써야 하기 때문에 발생한다.
2) 잠재적인 페이지 폴트 가능성을 제외하면 메모리에 맵핑된 파일을 읽고 쓰는 데 다른 시스템 콜 호출이나 컨텍스트 스위칭 오버헤드가 발생하지 않는다. 메모리에 접근하는 것만큼 단순하게 동작한다.
3) 여러 개의 프로세스가 같은 객체를 메모리에 맵핑한다면 데이터는 모든 프로세스사이에서 공유된다. 읽기전용이나 MAP_SHARED 모드로 쓰기가 가능하게 맵핑된 객체는 전체가 다 공유된다. MAP_PRIVATE 모드로 쓰기가 가능하게 맵핑된 객체는 copy-on-write 가 일어나기 전까지만 페이지를 공유한다.
4) lseek() 같은 시스템 콜을 사용하지 않고도 간단한 포인터 조작만으로 맵핑 영역을 탐색할 수 있다.
mmap의 단점
1) 메모리 맵핑은 항상 페이지 크기의 정수배만 가능하다. 따라서 맵핑하려는 파일 크기가 페이지 크기의 정수배 차이 만큼의 공간이 낭비된다.
2) 32bit 에서 다양한 크기의 수많은 맵핑을 사용하게 되면 주소 공간의 파편화를 초래하여 크기 연속된 비어 있는 공간을 찾기 어려워진다.
3) 메모리 맵핑과 관련 자료구조를 커널 내부에서 생성, 유지하는 데 오버헤드가 발생한다.
[오늘의 나는 어땠을까?]
오늘은 그냥 간단하게 오늘 하루를 쓰려고 한다.
수료 날이 다가올 수록 너무 불안하다.
내가 0주차를 끝내고 작성한 블로그 글에 나의 목표를 다 이룰 수 있을까?에 대한 불안감이다.
솔직히 가장 이루고 싶은 목표는 협력사에 취업에 성공하여 개발자 커리어를 시작하는 것이다.
더 구체적으로는 내가 목표로 하는 기업에 취업에 성공하는 것이다.
하고 싶지만 내가 할 수 있을까하는 생각 뿐이다.
너무 부족하고 그 부족함을 채워야하는데 잘 되지 않는 것같다.
내가 잘하고 있는지를 증명할 방법이 없다.
그냥 일단 내게 주어진 과제를 베이스로 하여 나만의 계획으로 움직이고 있다.
목표를 이뤄내고 싶다.
아래의 영상을 보며 그냥 명확한 목표가 있고 그 목표를 이루기 위해 미친듯이 노력하면 된다는 마인드를 가지기는 했다.
필요한 것은 미친듯한 노력과 명확한 목표.
https://www.youtube.com/watch?v=4jdhrf_bUrw
'기타 > SW 사관학교 정글' 카테고리의 다른 글
[SW 정글 88일차] File system 기초 개념 공부 마무리 (0) 2021.10.30 [SW 정글 87일차] File System 개념 공부 시작 (0) 2021.10.29 [SW 정글 85일차] Page Replacement Algorithm (0) 2021.10.27 [SW 정글 84일차] Project 3 - Memory Mapped Files (0) 2021.10.26 [SW 정글 83일차] 효율적으로 보낸 일요일 (2) 2021.10.25