* 메모리 맵 - mmap() <파일 혹은 디바이스를 메모리와 대응>
; 파일(리눅스에서는 디바이스도 파일로 처리하므로 디바이스도 메모리 맵으로 연결 가능)을 처리하기 위해서는 보통 저수준으로는 파일 디스크립터
* 특징
1. 생성된 메모리 맵을 포인터를 이용하여 쉽게 사용 가능하다.
2. 파일로 연결하여 사용시 메모리-파일 사이의 동기화가 편하다.
3. IPC(프로세스간 통신)로 활용 가능하다.
4. 대용량의 데이터를 사용할 시 성능이 향상된다.
* 주의점
- 메모리 맵은 바로 파일의 처리하는게 아니라 가상 메모리로 활용되는 페이지에 맵핑하는 방식이다. 그러므로 파일과 해당 메모리 맵이 된 페이지가 다른 공간이다. 그러므로 커널에 의해 여유 시간에 동기화(둘의 데이터가 같아지는..)가 될 때까지 서로 다른 데이터를 가질 수 있다. 그러므로 동기화에 대한 주의를 할 필요가 있다. <개발자가 직접 커널에 동기화를 명령 할 수 있는 함수도 있다. - fsync()>
IPC로 사용 할 때에도 프로세스간 동기화에 대한 주의도 필요하다.
* 2가지 방식
1. 공유 메모리 맵 방식 (Shred Memory-Map)
; 메모리 맵 변경 시 원본 파일과 데이터가 동기화가 되는 방식
2. 복사 메모리 맵 방식 (Private Memory-Map)
; 처음 메모리 맵에 매핑 될때 파일의 내용을 읽어와서 복사하고 그 이후 동기화 하지 않는 방식.
* 메모리 맵 생성 함수 - mmap()
void* mmap(void *state, size_t length, int prot, int flags, int fd, ott_t offset);
- void *state
; 할당받기 원하는 메모리 주소. 보통 0을 써서 커널이 적합한 공간을 임의로 할당해 주소를 받을 수 있고, 직접 입력하여 사용해도된다. 하지만 직접 입력하는 경우 해당 시스템의 페이지 (배수)단위로 주소 값을 설정해줘야 한다.
- size_t length
; 메모리 맵을 할 크기. 바이트 단위로 설정한다.
- int prot
; 메모리 보호 메커니즘. 플래그 형식이므로 비트 연산으로 복수 속성으로 지정 가능하다.
+ PROT_EXEC; 해당 페이지 실행 가능.
+ PROT_READ; 해당 페이지 읽기 가능.
+ PROT_WRITE; 해당 페이지 쓰기 가능.
+ PROT_NONE; 해당 페이지 접근 불가.
=> 매핑할 파일 디스크립터와 속성이 같아야한다.
- int flags
+ MAP_SHARED; 공유 메모리 맵 방식.
+ MAP_PRIVATE; 복사 메모리 맵 방식.
+ MAP_FIXED ; 메모리 시작 번지 지정시 사용.
=>MAP_SHARED/MAP_PRIVATE 둘 중에 한개만 지정해야된다.
- int fd
; 메모리 맵 방식을 사용할 파일 디스크립터.(파일 혹은 디바이스)
- ott_t offset
; 해당 파일 디스크립터에서 메모리 맵을 시작할 오프셋 값.
+ return value
; 메모리 맵핑이 이루어진 가상 메모리 주소. 실패시 MAP_FAILED가 발생하고 errno에 해당 상황에 대한 값이 설정된다.
* 메모리 맵 해제 - munmap()
; 메모리 맵을 사용하고 자원을 해제 할 때 사용한다.
int munmap(void *start, size_t length);
- void *start
; 메모리 맵핑이 시작된 주소. mmap()의 반환 값을 넣으면된다.
- size_t length
; 메모리 맵을 한 길이. mmap() 사용시 size_t length 인자와 크기를 주면된다.
+ return value
;성공 0, 실패 -1
* 메모리 맵과 파일의 동기화 - fsync()
; 메모리 맵에 데이터를 갱신해도 바로 파일과 동기화가 이루어지는 것은 아니다. 커널이 여유 있을 때 동기화를 수행한다. 그러므로 개발자가 직접 동기화를 보장하고 싶을 때 사용한다. 그리고 munmap()을 하여 메모리 맵을 해제 할때에도 동기화를 해주면 데이터가 보장된다.
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
===================================================================================
...
#define MMAP_FULENAME "test_mmap"
#define MMAP_SIZE 64
...
int main()
{
int fd;
char *p_mmap; //메모리 맵으로 사용할 데이터 타입
...
fd = open(MMAP_FILENAME, O_RDWR|O_CREAT, 0664);
...
p_mmap = (char*)mmap((void*)0, MMAP_SIZE, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
//공유 메모리 방식을 사용한다. 읽기/쓰기 가능
...
//memcpy(); 등으로 메모리 맵 데이터 갱신.
...
msync(p_mmap, MAP_SIZE, MS_SYNC);
...
munmap(p_mmap);
return 0;
}
=> 메모리 맵 할 파일 이름만 같으면 IPC도 된다.
'프로그래밍 > C++' 카테고리의 다른 글
비트연산 정리 (1) | 2011.11.21 |
---|---|
printf 출력 서식 (0) | 2011.10.18 |
C 언어 레퍼런스 - localtime 함수 (0) | 2011.10.13 |
[C++] 상속 두번째, 세가지 형태의 상속 (private, protected, public) (0) | 2011.03.03 |
매크로 (0) | 2010.12.21 |
Unicode 와 ANSI 문자의 변환을 해주는 매크로 (0) | 2010.12.11 |
가변인자 사용하기 (0) | 2010.11.12 |
const 위치에 따른 동작 (0) | 2010.11.12 |
함수 포인터 (0) | 2010.11.11 |
C++ 파일 입출력 (0) | 2010.10.27 |