일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 후디니
- Standard Stream
- foreground process
- 뷰포트
- houdini
- background process
- 섭페
- 3Ds max 기초
- bash shell 조건문
- mmap
- substance painter
- fork 시스템 콜
- 3D 배경 그래픽
- bg 명령어
- msync
- Redirection
- Symmetry
- atexit()
- ps 명령어
- 추가 업로딩 중
- 생활코딩 복습
- wait 시스템 콜
- exit()
- exec 시스템 콜
- 개체 외곽 하이라이트 기준선 없애는 법
- copy-on-write
- 섭페에서 텍스처 추출
- bash shell 반복문
- bash shell 변수
- pane & desktop
- Today
- Total
Researcher to Developer
mmap, msync, stat - 메모리와 파일 시스템 관련 시스템 콜 본문
malloc 함수
heap 영역에 동적메모리를 생성시킨다.
1. malloc () 함수로 동적메모리를 할당할 수 있다.
2. free () 함수로 해당 메모리를 해제할 수 있다.
메모리 조작 함수 종류
strcmp, strcpy, memset
파일 처리 성능 개선 기법 중
메모리에 파일을 매핑하는 시스템 콜에 대해서 알아보자.
mmap
프로세스에서 파일을 읽을 때는 시스템콜 호출, 스케줄러 관여, 인터럽트 관여 등의
메커니즘 때문에 복잡하고 시간이 오래 걸린다.
이 때 mmap 을 사용하는데, 파일을 메모리 특정 공간에 매핑을 해놓는다.
그러면 프로세스는 파일을 처리하는 것이 아니라 메모리를 읽거나 쓰면서
복잡한 과정을 거치지 않아 성능이 향상된다.
헤더 파일과 코드 예제는 다음과 같다.
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset
mmap의 리턴값은 메모리가 매핑이 정상적으로 되면 해당 메모리 주소값이 리턴이 됨
1. [start+offset] ~ [start+offset+length]만큼의 물리 메모리 공간을 mapping할 것을 요청
2. size_t : 메모리의 얼마만큼의 길이를 쓸꺼냐
3. 보통 start : NULL 또는 0 사용
4. 보통 offset : mapping 되기 원하는 물리 메모리 주소로 지정
5. prot : 보호 모드 설정, 권한 인자
- PROT_READ(읽기 가능) / PROT_WRITE(쓰기 가능) / PROT_EXEC(실행 가능) /
PROT_NONE(접근 불가)
6. flags : 메모리 주소 공간 설정
- MAP_SHARED(다른 프로세스와 공유 가능) / MAP_PRIVATE(프로세스 내에서만 사용 가능) /
MAP_FIXED(지정된 주소로 공간 지정)
7. fd : device file에 대한 file descriptor
예들 들어
start 가 0다
length 가 5다
offset 이 10이라면
start에서 10만큼 (offset 만큼) 떨어진 곳에서 5만큼(length) 영역이 파일에 매핑이 된다.
#mmap 동작 방식으로 이해하는 실제 메모리 동작
1. mmap 실행 시, 가상 메모리 주소에 file 주소 매핑 (가상 메모리 이해)
페이지 x번 부터 y번까지 할당됨
페이지 디렉토리 중 사용 디렉토리만 페이지 테이블을 구성한다.
2. 해당 메모리 접근 시, (요구 페이징, lazy allocation)
페이지 폴트 인터럽트 발생
OS에서 file data를 복사해서 해당 물리 메모리 페이지에 넣어준다.
3. 메모리 read 시 해당 물리 페이지 데이터를 읽으면 됨 (메모리 access 만 필요한 것)
4. 메모리 write 시 해당 물리 페이지 데이터 수정 후, 페이지 상태 flag 중
dirty bit(알고리즘에 따라 이름이 바뀔 수 있음)를 1로 수정
5. 파일 close 시, mmap을 더 이상 사용하지 않을 때라던지,
mmap으로 매핑된 메모리를 파일에 싱크, 저장을 강제로 할 때 라던지 그 때
물리 페이지 데이터가 file에 업데이트 됨 → 성능 개선
mmap 을 이용하면 파일 access 빈도수가 굉장히 적기 때문에 성능이 많이 개선된다.
#mmap 장단점
장점
read, write 시 반복적인 파일 접근을 방지하여 성능 개선
mapping 된 영역은 파일 처리를 위한 lseek() 을 사용하지 않고 간단한 포인터 조작으로 탐색 가능
단점
mmap은 페이지 사이즈 단위로 매핑
페이지 사이즈 단위의 정수배가 아닌 경우, 한 페이지 정도의 공간 추가 할당 및 남은 공간을
0으로 채워주게 된다.
페이지 단위로 매핑하기 때문에 추가공간이 필요하거나 공간 낭비가 있을 수 있다.
#mmap 해제
int munmap(void *addr, size_t length_
*addr 에 mapping된 물리 메모리 주소를 해제한다.
length : mapping된 메모리의 크기(mmap에서 지정했던 동일 값을 넣는다.)
#msync
메모리에 있는 값이 변경이 되면
해당 파일에 업데이트 해줘야 하잖아요??
이를 강제적으로 해주는 함수가
msync
mmap을 사용해 맵핑한 메모리 주소 영역에 대해 동기화를 하기 위한 함수
int msync(void *start, size_t length, int flags);
start : mman()을 통해 리턴 받은 메모리 맵의 시작 주소
length : 동기화를 할 길이. 시작 주소로 부터 길이를 지정하면 된다.
flags
MS_ASYNA : 비동기 방식, 동기화(Memory → File)하라는 명령만 내리고 결과에
관계 없이 다음 코드 실행 (따라서, 동기화가 완료 안된 상태로 다음 코드 실행 가능)
MS_SYNC : 동기 방식, 동기화(Memory → File)가 될 때까지 블럭 상태로 대기
MS_INVALIDATE : 현재 메모리 맵을 무효화하고 파일의 데이터로 갱신. 즉 File → Memory
#inode 방식 파일 시스템
기본 개념
프로세스 마다 pid가 존재하고 pid 별로 PCB가 존재한다.
이와 마찬가지로 파일도 파일마다 inode 값이 존재하고 inode 별로 구조체를 가지고 있다.
inode 구조체
Mode 파일 종류나 권한(rwx) 정보
Owner Info 소유자, 소유 그룹 정보
Size 파일 크기 정보
Timestamps 생성, 수정 등의 시간 정보
Direct blocks (12개) 직접적으로 주소를 가리킴
Single indirect
Double indirect
Triple indirect
stat
inode 정보를 한 번에 가져올 수 있는 시스템 콜
inode 메타 데이터
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int filedes, struct stat *buf);
inode 메타 데이터 - stat 구조체 일부분
struct stat {
dev_t st_dev; / ID of device containing file
ino_t st_ino; / inode number
mode_t st_mode; / 파일 종류 및 접근 권한
nlink_t st_nlink; / 이 구조체에 hardlink 된 횟수
uid_t st_uid; / 파일 owner
gid_t st_gid; / group ID of owner
dev_t st_rdev; / device ID (if special file)
off_t st_size; / 파일 크기(bytes)
blksize_t st_blksize; / blocksize(4KB) for file system I/O
blkcnt_t st_blocks; / number of 512B blocks allocated
time_t st_atime; / time of last access
time_t st_mtime; / time of last modification
time_t st_ctime; / time of last status change
};