mmap, msync, munmap
<mmap>
1.1. 사용법
#include <sys/mman.h>
void * mmap(void *start, size_t length, int prot, int flags, int flides, off_t offset);
1.2. 설명
mmap() 함수는 flides로 지정된 파일(혹은 다른 객체)에서 offset을 시작으로 length바이트 만큼을 start주소로 대응시키도록 한다. start주소는 단지 그 주소를 사용했으면 좋겠다는 정도로 보통 0을 지정한다. mmap는 지정된 영역이 대응된 실제 시작위치를 반환한다. prot인자는 원하는 메모리 보호모드를 설정한다. 사용할 수 있는 비트는 다음과 같다.
PROT_EXEC
페이지는 실행 가능하다.
PROT_READ
페이지는 읽을 수 있다.
PROT_WRITE
페이지는 쓰여질 수 있다.
PROT_NONE
페이지는 접근할 수 없다.
위와 같이 prot 비트는 4가지가 있지만, 주로 사용하는 비트는 PROT_READ, PROT_WRITE다.
모든 권한을 주려면 PROT_ALL (PROT_READ|PROT_WRITE|PROD_USER|PROT_EXEC)를 사용하면 된다.
flags는 대응된 객체의 타입, 대응 옵션, 대응된 페이지 복사본에 대한 수정이 그 프로세스에서만 보일 것인지 아니면, 다른 참조하는 프로세스와 공유할 것인지를 설정한다. 다음과 같은 비트들을 사용할 수 있다.
MAP_FIXED
지정된 주소 이외의 다른 주소를 선택하지 않는다. 지정된 주소가 사용될 수 없다면 mmap()는 실패한다. 만일 MAP_FIXED가 지정되면, start는 페이지 크기의 배수이어야 한다. 이 옵션은 사용하지 않는 것이 좋다.
MAP_SHARED
대응된 객체를 다른 모든 프로세스와 공유한다.
MAP_PRIVATE
개별적인 copy-on-write 대응을 만든다.(다른 프로세스와 대응 영역을 공유하지 않는다).
위의 3개의 플래그는 POSIX.1b에 규정되어 있다. 리눅스는 MAP_DENYWRITE, MAP_EXECUTABLE, MAP_ANON(YMOUS)도 지원한다. munmap() 는 지정된 주소 공간에 대한 대응을 푼다. 범위내의 주소에 대한 참조 계수를 늘려서 유효하지 않은 메모리 참조로 만든다.
1.3. 반환값
성공시, mmap()는 내응된 영역의 포인터를 반환한다. 에러시에는 -1(MAP_FAILED)이 리턴되며, errno는 적당한 값으로 설정된다. munmap()는 0을 리턴하며, 실패시 -1이 리턴되며, errno가 설정된다.
1.4. 에러
EBADF
fd가 유효한 파일 기술자가 아니다.
EACCES
MAP_PRIVATE가 설정되어 있지만 fd가 읽을 수 있도록 열려 있지 않다. 또는 MAP_SHARED와 RPOT_WRITE가 설정되어 있지만 fd가 쓸 수 있도록 열려있지 않다.
EINVAL
start나 length나 offset이 적당하지 않다. 보통 너무 크거나 PAGESIZE 경계로 정렬되어 있지 않을 경우.
EAGAIN
파일이 잠겨 있다. file descriptor가 열려 있지 않다.
ENOMEM
사용할 수 있는 메모리가 없다.
1.5. 예제
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd;
char *file = NULL;
struct stat sb;
char buf[80] ={0x00,};
int flag = PROT_WRITE | PROT_READ;
if (argc < 2)
{
fprintf(stderr, "Usage: input\n");
exit(1);
}
if ((fd = open(argv[1], O_RDWR|O_CREAT)) < 0)
{
perror("File Open Error");
exit(1);
}
if (fstat(fd, &sb) < 0)
{
perror("fstat error");
exit(1);
}
file = (char *)malloc(40);
// mmap를 이용해서 열린 파일을 메모리에 대응시킨다.
// file은 대응된 주소를 가리키고, file을 이용해서 필요한 작업을
// 하면 된다.
if ((file =
(char *) mmap(0, 40, flag, MAP_SHARED, fd, 0)) == -1)
{
perror("mmap error");
exit(1);
}
printf("%s\n", file);
memset(file, 0x00, 40);
munmap(file);
close(fd);
}
<msync>
1.1. 사용법
#include <sys/mman.h>
int msync ( void *start, size_t length, int flags)
- void *start : mmap()을 통해 리턴 받은 메모리 맵의 시작 주소
- size_t length : 동기화를 할 길이, 시작 주소로부터 길이를 지정하면 된다.
- int flags : 아래 플래그를 사용한다.
MS_ASYNC
비동기 방식, 동기화 (memory->file)하라는 명령만 내리고 결과에 관계 없이 바로 리턴, 그렇기 때문에 동기화 확인이 불가능하다.
MS_SYNC
동기방식, 동기화(memory->file)가 될 때까지 블록 상태로 대기한다.
MS_INVALIDATE
현재 메모리 맵을 무효화하고 파일의 데이터로 갱신, 즉File -> Memory
1.2. 설명
메모리에 있는 내용과 파일을 동기화 시킨다.
1.3. 반환값
성공적으로 동기화가 이뤄지면 : 0
그렇지 않을시: -1 , 혹은 에러에 해당하는 errno가 리턴
1.4. 에러
EBUSY
주소의 일부 혹은 전체의 lock이 걸려 있다. MS_SYNC와 MS_INVALIDATE옵션이 함께 설정되어있는 경우 발생
EAGAIN
페이지의 일부 혹은 전체가 I/O를 위해 lock이 걸려있는 상태
EINVAL
start나 length나 offset이 적당하지 않다. 보통 너무 크거나 PAGESIZE 경계로 정렬되어 있지 않을 경우. flags가 MS_ASYNC , MS_INVALIDATE의 복합이 아닌 경우
EIO
파일 시스템에서 읽어 들이거나 쓸 때 일어나는 오류
ENOMEM
주소나 매핑된 페이지의 허용범위를 넘는 경우
EPERM
MS_INVALIDATE 설정 되어 있고 하나 이상의 페이지가 메모리가 lock이 걸려있는 경우.
<munmap>
1.1. 사용법
#include <sys/mman.h>
int munmap(void *addr, size_t len);
- void *addr: mmap()을 통해 리턴 받은 메모리 맵의 시작 주소
- size_t len : 메모리 해제할 주소의 길이
1.2. 설명
매핑되어 있는 메모리를 해제한다..
1.3. 반환값
성공적으로 메모리가 해제되면 이뤄지면 : 0
그렇지 않을시: -1 , 혹은 에러에 해당하는 errno가 리턴
1.4. 에러
EINVAL
address가 허용 범위를 초과한 경우, 혹은 length 아규먼트가 0과 같거나 적을 경우.
끝.
'IT > programming' 카테고리의 다른 글
[PYTHON] 유효한 날짜 포맷 확인 / datetime (1) | 2022.01.27 |
---|---|
[C/C++] C언어 파일 생성/삭제 이벤트 모니터링 / inotify, event monitoring (1) | 2022.01.20 |
[C/C++] C언어 프로그램/함수 실행 시간 측정, us 마이크로초 기준 (4) | 2022.01.18 |
[C/C++] C++ 프로그램/함수 실행 시간 측정, ms 밀리초 기준 (0) | 2022.01.18 |
[JAVA] 클래스와 메서드 설명 (0) | 2022.01.18 |
댓글