mmap(2) - wariua/manpages-ko GitHub Wiki

NAME

mmap, munmap - νŒŒμΌμ΄λ‚˜ μž₯치λ₯Ό λ©”λͺ¨λ¦¬λ‘œ λ§΅ ν•˜κ±°λ‚˜ ν•΄μ œν•˜κΈ°

SYNOPSIS

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);
int munmap(void *addr, size_t length);

κΈ°λŠ₯ 확인 맀크둜 μš”κ±΄μ— λŒ€ν•œ μ •λ³΄λŠ” NOTESλ₯Ό 보라.

DESCRIPTION

mmap()은 호좜 ν”„λ‘œμ„ΈμŠ€μ˜ 가상 μ£Όμ†Œ 곡간 μ•ˆμ— μƒˆ 맀핑을 λ§Œλ“ λ‹€. addrμ—λŠ” μƒˆ λ§€ν•‘μ˜ μ‹œμž‘ μ£Όμ†Œλ₯Ό μ§€μ •ν•œλ‹€. length μΈμžλŠ” λ§€ν•‘μ˜ 길이(0보닀 컀야 함)λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

addr이 NULL이면 맀핑을 생성할 (νŽ˜μ΄μ§€μ— μ •λ ¬λœ) μ£Όμ†Œλ₯Ό μ»€λ„μ—μ„œ μ„ νƒν•œλ‹€. 이게 μƒˆ 맀핑을 λ§Œλ“œλŠ” κ°€μž₯ 이식성 쒋은 방식이닀. addr이 NULL이 μ•„λ‹ˆλ©΄ μ»€λ„μ—μ„œ 이λ₯Ό 맀핑을 λ‘˜ μœ„μΉ˜μ— λŒ€ν•œ 힌트둜 받아듀인닀. λ¦¬λˆ…μŠ€ 컀널에선 κ°€κΉŒμš΄ νŽ˜μ΄μ§€ κ²½κ³„λ‘œ (ν•˜μ§€λ§Œ 항상 /proc/sys/vm/mmap_min_addr에 μ§€μ •ν•œ κ°’ μ΄μƒμœΌλ‘œ) μ •ν•œλ‹€. μƒˆ λ§€ν•‘μ˜ μ£Όμ†Œλ₯Ό 호좜 결과둜 λ°˜ν™˜ν•œλ‹€.

파일 λ§€ν•‘μ˜ λ‚΄μš©μ€ (읡λͺ… λ§€ν•‘κ³Ό 달리, μ•„λž˜ MAP_ANONYMOUS μ°Έκ³ ) 파일 λ””μŠ€ν¬λ¦½ν„° fdκ°€ κ°€λ¦¬ν‚€λŠ” 파일의 (λ˜λŠ” λ‹€λ₯Έ 객체의) μ˜€ν”„μ…‹ offset의 length 개 λ°”μ΄νŠΈλ‘œ μ±„μ›Œμ§„λ‹€. offset은 sysconf(_SC_PAGE_SIZE)κ°€ λ°˜ν™˜ν•˜λŠ” νŽ˜μ΄μ§€ 크기의 λ°°μˆ˜μ—¬μ•Ό ν•œλ‹€.

mmap() 호좜 λ°˜ν™˜ 후에 μ¦‰μ‹œ fdλ₯Ό 닫을 수 μžˆλ‹€. κ·Έλ ‡κ²Œ 해도 맀핑이 λ¬΄νš¨ν™”λ˜μ§€ μ•ŠλŠ”λ‹€.

prot μΈμžλŠ” 맀핑에 μ›ν•˜λŠ” λ©”λͺ¨λ¦¬ 보호 방식을 κΈ°μˆ ν•œλ‹€. (파일의 μ—΄κΈ° λͺ¨λ“œμ™€ μΆ©λŒν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.) PROT_NONEμ΄κ±°λ‚˜ λ‹€μŒ ν”Œλž˜κ·Έλ“€ 쀑 ν•˜λ‚˜ 이상을 λΉ„νŠΈ OR ν•œ 것이닀.

PROT_EXEC
νŽ˜μ΄μ§€λ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€.
PROT_READ
νŽ˜μ΄μ§€λ₯Ό 읽을 수 μžˆλ‹€.
PROT_WRITE
νŽ˜μ΄μ§€μ— μ“Έ 수 μžˆλ‹€.
PROT_NONE
νŽ˜μ΄μ§€μ— μ ‘κ·Όν•  수 μ—†λ‹€.

flags μΈμžλŠ” 맀핑에 λŒ€ν•œ κ°±μ‹  λ‚΄μš©μ΄ 같은 μ˜μ—­μ„ λ§΅ ν•˜κ³  μžˆλŠ” λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ λ³΄μ΄λŠ”μ§€ μ—¬λΆ€λ₯Ό, 그리고 κ·Έ κ°±μ‹  λ‚΄μš©μ΄ 기반 νŒŒμΌκΉŒμ§€ κ°€κ²Œ λ˜λŠ”μ§€ μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€. λ‹€μŒ 쀑 μ •ν™•νžˆ ν•œ 개 값을 flags에 μ§‘μ–΄λ„£μ–΄μ„œ λ™μž‘ 방식을 μ •ν•œλ‹€.

MAP_SHARED
맀핑을 κ³΅μœ ν•œλ‹€. 맀핑에 λŒ€ν•œ κ°±μ‹  λ‚΄μš©μ΄ 같은 μ˜μ—­μ„ λ§΅ ν•˜κ³  μžˆλŠ” λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ 보이며 (파일 기반 맀핑인 경우) κ·Έ κ°±μ‹  λ‚΄μš©μ΄ 기반 νŒŒμΌκΉŒμ§€ κ°„λ‹€. (κ°±μ‹  λ‚΄μš©μ΄ 기반 파일둜 κ°€λŠ” μ‹œμ μ„ μ •ν™•νžˆ μ œμ–΄ν•˜λ €λ©΄ msync(2)λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.)
MAP_SHARED_VALIDATE (λ¦¬λˆ…μŠ€ 4.15λΆ€ν„°)
이 ν”Œλž˜κ·Έμ˜ λ™μž‘ 방식은 MAP_SHARED와 κ°™λ˜, MAP_SHARED λ§€ν•‘μ—μ„œλŠ” flags에 λͺ¨λ₯΄λŠ” ν”Œλž˜κ·Έκ°€ 있으면 λ¬΄μ‹œν•œλ‹€λŠ” 점이 λ‹€λ₯΄λ‹€. 반면 MAP_SHARED_VALIDATE둜 맀핑을 λ§Œλ“€ λ•ŒλŠ” μ „λ‹¬λœ ν”Œλž˜κ·Έλ“€μ΄ λͺ¨λ‘ μ•Œλ €μ§„ 것인지 μ»€λ„μ—μ„œ κ²€μ‚¬ν•΄μ„œ λͺ¨λ₯΄λŠ” ν”Œλž˜κ·Έκ°€ 있으면 EOPNOTSUPP 였λ₯˜λ‘œ 맀핑이 μ‹€νŒ¨ν•œλ‹€. 또 일뢀 λ§€ν•‘ ν”Œλž˜κ·Έ(κ°€λ Ή MAP_SYNC)λ₯Ό μ‚¬μš©ν•˜λ €λ©΄ 이 λ§€ν•‘ μœ ν˜•μ΄ ν•„μš”ν•˜λ‹€.
MAP_PRIVATE
λΉ„κ³΅μœ  copy-on-write 맀핑을 λ§Œλ“ λ‹€. 맀핑에 λŒ€ν•œ κ°±μ‹  λ‚΄μš©μ΄ 같은 νŒŒμΌμ„ λ§΅ ν•˜κ³  μžˆλŠ” λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—κ²Œ 보이지 μ•ŠμœΌλ©° 기반 νŒŒμΌκΉŒμ§€ κ°€μ§€ μ•ŠλŠ”λ‹€. mmap() 호좜 후에 νŒŒμΌμ—μ„œ μΌμ–΄λ‚œ λ³€κ²½ λ‚΄μš©μ΄ λ§΅ 된 μ˜μ—­μ— λ³΄μ΄λŠ”μ§€ μ—¬λΆ€λŠ” λͺ…μ„Έλ˜μ–΄ μžˆμ§€ μ•Šλ‹€.

MAP_SHARED와 MAP_PRIVATE λͺ¨λ‘ POSIX.1-2001 및 POSIX.1-2008에 기술돼 μžˆλ‹€. MAP_SHARED_VALIDATEλŠ” λ¦¬λˆ…μŠ€ ν™•μž₯이닀.

λ”λΆˆμ–΄ flags에 λ‹€μŒ 값듀을 0개 이상 OR ν•  수 μžˆλ‹€.

MAP_32BIT (λ¦¬λˆ…μŠ€ 2.4.20, 2.6λΆ€ν„°)
맀핑을 ν”„λ‘œμ„ΈμŠ€ μ£Όμ†Œ κ³΅κ°„μ˜ 처음 2κΈ°κ°€λ°”μ΄νŠΈ μ•ˆμ— λ„£λŠ”λ‹€. x86-64 μƒμ—μ„œ 64λΉ„νŠΈ ν”„λ‘œκ·Έλž¨μ—λ§Œ 이 ν”Œλž˜κ·Έλ₯Ό μ§€μ›ν•œλ‹€. μŠ€λ ˆλ“œ μŠ€νƒμ„ λ©”λͺ¨λ¦¬μ˜ 처음 2GB λ‚΄μ˜ μ–΄λ”˜κ°€μ— ν• λ‹Ήν•΄μ„œ 일뢀 초기 64λΉ„νŠΈ ν”„λ‘œμ„Έμ„œλ“€μ—μ„œ λ¬Έλ§₯ μ „ν™˜ μ„±λŠ₯을 κ°œμ„ ν•  수 μžˆλ„λ‘ μΆ”κ°€λœ 것이닀. μš”μ¦˜μ˜ x86-64 ν”„λ‘œμ„Έμ„œμ—λŠ” 이런 μ„±λŠ₯ λ¬Έμ œκ°€ μ—†κΈ° λ•Œλ¬Έμ— 이 ν”Œλž˜κ·Έλ₯Ό μ“Έ ν•„μš”κ°€ μ—†λ‹€. MAP_FIXEDκ°€ 섀정돼 μžˆλŠ” 경우 MAP_32BIT ν”Œλž˜κ·Έλ₯Ό λ¬΄μ‹œν•œλ‹€.
MAP_ANON
MAP_ANONYMOUS의 λ™μ˜μ–΄. 제거 μ˜ˆμ •.
MAP_ANONYMOUS
맀핑이 νŒŒμΌμ„ 기반으둜 ν•˜μ§€ μ•ŠμœΌλ©° λ‚΄μš©λ¬Όμ΄ 0으둜 μ±„μ›Œμ§„λ‹€. fd 인자λ₯Ό λ¬΄μ‹œν•œλ‹€. ν•˜μ§€λ§Œ 일뢀 κ΅¬ν˜„μ—μ„œλŠ” MAP_ANONYMOUS (λ˜λŠ” MAP_ANON) μ§€μ • μ‹œ fdκ°€ -1이기λ₯Ό μš”κ΅¬ν•˜λ―€λ‘œ 이식 κ°€λŠ₯ν•œ μ‘μš©μ—μ„œλŠ” κ·Έλ ‡κ²Œ ν•˜λŠ” 게 μ’‹λ‹€. offset μΈμžλŠ” 0이어야 ν•  것이닀. MAP_ANONYMOUSλ₯Ό MAP_SHARED와 κ²°ν•©ν•΄ μ“°λŠ” 것은 λ¦¬λˆ…μŠ€ 컀널 2.4λΆ€ν„° μ§€μ›ν•œλ‹€.
MAP_DENYWRITE
이 ν”Œλž˜κ·ΈλŠ” λ¬΄μ‹œν•œλ‹€. (μ˜ˆμ „μ—λŠ” (λ¦¬λˆ…μŠ€ 2.0 및 κ·Έ μ „μ—μ„œλŠ”) 기반 νŒŒμΌμ— λŒ€ν•œ μ“°κΈ°κ°€ ETXTBUSY둜 μ‹€νŒ¨ν•΄μ•Ό ν•œλ‹€λŠ” λœ»μ΄μ—ˆλ‹€. ν•˜μ§€λ§Œ μ„œλΉ„μŠ€ κ±°λΆ€ 곡격의 원인이 됐닀.)
MAP_EXECUTABLE
이 ν”Œλž˜κ·ΈλŠ” λ¬΄μ‹œν•œλ‹€.
MAP_FILE
ν˜Έν™˜μš© ν”Œλž˜κ·Έ. λ¬΄μ‹œν•œλ‹€.
MAP_FIXED

addr을 힌트둜 ν•΄μ„ν•˜μ§€ μ•ŠλŠ”λ‹€. 즉 μ •ν™•νžˆ κ·Έ μ£Όμ†Œμ— 맀핑을 μœ„μΉ˜μ‹œν‚¨λ‹€. addr이 적절히 정렬돼 μžˆμ–΄μ•Ό ν•œλ‹€. λŒ€λΆ€λΆ„μ˜ μ•„ν‚€ν…μ²˜μ—μ„œλŠ” νŽ˜μ΄μ§€ 크기의 배수이면 μΆ©λΆ„ν•˜μ§€λ§Œ μ–΄λ–€ μ•„ν‚€ν…μ²˜μ—μ„œλŠ” μΆ”κ°€ μ œμ•½μ΄ μžˆμ„ 수 μžˆλ‹€. addrκ³Ό len으둜 μ§€μ •ν•œ λ©”λͺ¨λ¦¬ μ˜μ—­μ΄ κΈ°μ‘΄ λ§€ν•‘(λ“€)의 νŽ˜μ΄μ§€μ™€ κ²ΉμΉ˜λŠ” κ²½μš°μ—λŠ” κΈ°μ‘΄ λ§€ν•‘μ˜ κ²ΉμΉ˜λŠ” 뢀뢄을 λ²„λ¦¬κ²Œ λœλ‹€. μ§€μ •ν•œ μ£Όμ†Œλ₯Ό μ‚¬μš©ν•  수 μ—†μœΌλ©΄ mmap()이 μ‹€νŒ¨ν•˜κ²Œ λœλ‹€.

이식성이 있기λ₯Ό λ°”λΌλŠ” μ†Œν”„νŠΈμ›¨μ–΄μ—μ„œλŠ” MAP_FIXED ν”Œλž˜κ·Έλ₯Ό μ‘°μ‹¬ν•΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. ν”„λ‘œμ„ΈμŠ€ λ©”λͺ¨λ¦¬ λ§€ν•‘λ“€μ˜ μ •ν™•ν•œ λ°°μΉ˜κ°€ 컀널 버전, C 라이브러리 버전, 운영 체제 λ¦΄λ¦¬μŠ€μ— 따라 크게 λ‹€λ₯Ό 수 μžˆλ‹€λŠ” 점에 μœ λ…ν•΄μ•Ό ν•œλ‹€. NOTES에 μžˆλŠ” 이 ν”Œλž˜κ·Έμ— λŒ€ν•œ λ‚΄μš©μ„ μ£Όμ˜ν•΄μ„œ 읽어 보라!

MAP_FIXED_NOREPLACE (λ¦¬λˆ…μŠ€ 4.17λΆ€ν„°)

이 ν”Œλž˜κ·Έμ˜ λ™μž‘ 방식은 addr κ°•μ œλΌλŠ” μ μ—μ„œ MAP_FIXED와 λΉ„μŠ·ν•œλ°, MAP_FIXED_NOREPLACEλŠ” μ ˆλŒ€ κΈ°μ‘΄ λ§€ν•‘ λ²”μœ„λ₯Ό μ†μƒμ‹œν‚€μ§€ μ•ŠλŠ”λ‹€λŠ” 점이 λ‹€λ₯΄λ‹€. μš”μ²­ λ²”μœ„κ°€ κΈ°μ‘΄ λ§€ν•‘κ³Ό μΆ©λŒν•˜λ €λŠ” κ²½μš°μ— 이 ν˜ΈμΆœμ€ EEXIST 였λ₯˜λ‘œ μ‹€νŒ¨ν•œλ‹€. λ”°λΌμ„œ 이 ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•˜λ©΄ (λ‹€λ₯Έ μŠ€λ ˆλ“œλ“€μ— λŒ€ν•΄) μ›μžμ μœΌλ‘œ μ£Όμ†Œ λ²”μœ„ 맀핑을 μ‹œλ„ν•  수 μžˆλ‹€. ν•œ μŠ€λ ˆλ“œλ§Œ μ„±κ³΅ν•˜κ³  λ‚˜λ¨Έμ§€λŠ” μ‹€νŒ¨λ₯Ό λ³΄κ³ ν•˜κ²Œ λœλ‹€.

참고둜 MAP_FIXED_NOREPLACE ν”Œλž˜κ·Έλ₯Ό μΈμ‹ν•˜μ§€ λͺ»ν•˜λŠ” ꡬ식 컀널듀은 (κΈ°μ‘΄ λ§€ν•‘κ³Όμ˜ μΆ©λŒμ„ νƒμ§€ν–ˆμ„ λ•Œ) 보톡 "λΉ„-MAP_FIXED" λ™μž‘ λ°©μ‹μœΌλ‘œ ν›„ν‡΄ν•˜κ²Œ λœλ‹€. 즉 μš”μ²­ν•œ μ£Όμ†Œμ™€ λ‹€λ₯Έ μ£Όμ†Œλ₯Ό λ°˜ν™˜ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ ν•˜μœ„ ν˜Έν™˜μ„± μžˆλŠ” μ†Œν”„νŠΈμ›¨μ–΄μ—μ„œλŠ” λ°˜ν™˜ μ£Όμ†Œκ°€ μš”μ²­ μ£Όμ†Œμ™€ 같은지 확인할 ν•„μš”κ°€ μžˆλ‹€.

MAP_GROWSDOWN
μŠ€νƒμ— μ“°λŠ” ν”Œλž˜κ·Έλ‹€. 맀핑이 λ©”λͺ¨λ¦¬μ—μ„œ μ•„λž˜ λ°©ν–₯으둜 λŠ˜μ–΄λ‚˜μ•Ό ν•œλ‹€κ³  컀널 가상 λ©”λͺ¨λ¦¬ μ‹œμŠ€ν…œμ—κ²Œ μ•Œλ¦°λ‹€. λ°˜ν™˜ μ£Όμ†ŒλŠ” ν”„λ‘œμ„ΈμŠ€ 가상 μ£Όμ†Œ 곡간에 μ‹€μ œ μƒμ„±ν•œ λ©”λͺ¨λ¦¬ μ˜μ—­λ³΄λ‹€ ν•œ νŽ˜μ΄μ§€ μ•„λž˜μ˜ μ£Όμ†Œμ΄λ‹€. λ§€ν•‘ μ•„λž˜μ˜ κ·Έ "방호 ꡬ역" νŽ˜μ΄μ§€ λ‚΄μ˜ μ£Όμ†Œλ₯Ό κ±΄λ“œλ¦¬λ©΄ 맀핑이 ν•œ νŽ˜μ΄μ§€λ§ŒνΌ μ„±μž₯ν•˜κ²Œ λœλ‹€. κ·Έ μ„±μž₯이 반볡될 수 있으며, 맀핑이 μ•„λž˜μͺ½ λ‹€μŒ λ§€ν•‘μ˜ μ΅œμƒλ‹¨ νŽ˜μ΄μ§€λ‘œ μ„±μž₯ν•΄μ•Ό ν•˜λŠ” μ‹œμ μ— "방호 ꡬ역" νŽ˜μ΄μ§€λ₯Ό κ±΄λ“œλ¦¬λ©΄ SIGSEGV μ‹œκ·Έλ„μ΄ λ°œμƒν•˜κ²Œ λœλ‹€.
MAP_HUGETLB (λ¦¬λˆ…μŠ€ 2.6.32λΆ€ν„°)
"κ±°λŒ€ νŽ˜μ΄μ§€"둜 맀핑을 ν• λ‹Ήν•œλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ λ¦¬λˆ…μŠ€ 컀널 μ†ŒμŠ€ 파일 Documentation/admin-guide/mm/hugetlbpage.rstλ₯Ό 보라. μ•„λž˜ NOTES도 μ°Έκ³ .
MAP_HUGE_2MB, MAP_HUGE_1GB (λ¦¬λˆ…μŠ€ 4.8λΆ€ν„°)

μ—¬λŸ¬ κ°€μ§€ hugetlb νŽ˜μ΄μ§€ 크기λ₯Ό μ§€μ›ν•˜λŠ” μ‹œμŠ€ν…œμ—μ„œ MAP_HUGETLB와 μ‘°ν•©ν•΄ μ‚¬μš©ν•΄μ„œ λ‹€λ₯Έ hugetlb νŽ˜μ΄μ§€ 크기(각각 2MB와 1GB)λ₯Ό μ„ νƒν•œλ‹€.

더 μΌλ°˜μ μœΌλ‘œλŠ” μ˜€ν”„μ…‹ MAP_HUGE_SHIFT의 μ—¬μ„― λΉ„νŠΈμ— μ›ν•˜λŠ” νŽ˜μ΄μ§€ 크기의 λ°‘μˆ˜ 2 둜그λ₯Ό 인코딩 ν•΄μ„œ μ›ν•˜λŠ” κ±°λŒ€ νŽ˜μ΄μ§€ 크기λ₯Ό μ„€μ •ν•  수 μžˆλ‹€. (이 λΉ„νŠΈ ν•„λ“œμ—μ„œ 0 값은 κΈ°λ³Έ κ±°λŒ€ νŽ˜μ΄μ§€ 크기이닀. κΈ°λ³Έ κ±°λŒ€ νŽ˜μ΄μ§€ ν¬κΈ°λŠ” /proc/meminfo에 λ‚˜μ˜€λŠ” Hugepagesize ν•„λ“œλ₯Ό 톡해 μ•Œ 수 μžˆλ‹€.) λ”°λΌμ„œ μœ„ 두 μƒμˆ˜λŠ” λ‹€μŒκ³Ό 같이 μ •μ˜λΌ μžˆλ‹€.

#define MAP_HUGE_2MB    (21 << MAP_HUGE_SHIFT)
#define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)

/sys/kernel/mm/hugepages의 ν•˜μœ„ 디렉터리λ₯Ό ν™•μΈν•˜λ©΄ μ‹œμŠ€ν…œμ—μ„œ μ§€μ›ν•˜λŠ” κ±°λŒ€ νŽ˜μ΄μ§€ 크기듀을 μ•Œ 수 μžˆλ‹€.

MAP_LOCKED (λ¦¬λˆ…μŠ€ 2.5.37λΆ€ν„°)
λ§΅ ν•œ μ˜μ—­μ„ mlock(2)κ³Ό 같은 λ°©μ‹μœΌλ‘œ κ³ μ •ν•˜κ²Œ ν‘œμ‹œν•œλ‹€. μ—¬κΈ°μ„  전체 λ²”μœ„λ₯Ό μ±„μš°λ €κ³  (미리 폴트) μ‹œλ„λŠ” ν•˜μ§€λ§Œ μ‹€νŒ¨ν•œ κ²½μš°μ— mmap() 호좜이 μ‹€νŒ¨ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ 이후에 메이저 ν΄νŠΈκ°€ λ°œμƒν•  μˆ˜λ„ μžˆλ‹€. 즉 mlock(2)만큼 의미둠이 κ°•λ ₯ν•˜μ§€ μ•Šλ‹€. λ§€ν•‘ μ΄ˆκΈ°ν™” ν›„μ˜ 메이저 폴트λ₯Ό ν—ˆμš©ν•  수 μ—†λ‹€λ©΄ mmap()에 mlock(2)을 λ”ν•΄μ„œ μ“°λŠ” 게 μ’‹λ‹€. ꡬ식 μ»€λ„μ—μ„œλŠ” MAP_LOCKED ν”Œλž˜κ·Έλ₯Ό λ¬΄μ‹œν•œλ‹€.
MAP_NONBLOCK (λ¦¬λˆ…μŠ€ 2.5.46λΆ€ν„°)
이 ν”Œλž˜κ·ΈλŠ” MAP_POPULATE와 ν•¨κ»˜ μ“Έ λ•Œλ§Œ μ˜λ―Έκ°€ μžˆλ‹€. 미리 읽기λ₯Ό μˆ˜ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€. 즉 이미 램 내에 μžˆλŠ” νŽ˜μ΄μ§€μ—λ§Œ νŽ˜μ΄μ§€ ν…Œμ΄λΈ” ν•­λͺ©μ„ λ§Œλ“ λ‹€. λ¦¬λˆ…μŠ€ 2.6.23λΆ€ν„°λŠ” 이 ν”Œλž˜κ·Έλ₯Ό μ“°λ©΄ MAP_POPULATEκ°€ 아무것도 ν•˜μ§€ μ•Šκ²Œ λœλ‹€. μ–Έμ  κ°€ MAP_POPULATE와 MAP_NONBLOCK의 쑰합이 μž¬κ΅¬ν˜„λ  μˆ˜λ„ μžˆλ‹€.
MAP_NORESERVE
이 맀핑을 μœ„ν•œ μŠ€μ™‘ 곡간을 μ˜ˆλΉ„ν•΄ 두지 μ•ŠλŠ”λ‹€. μŠ€μ™‘ 곡간이 μ˜ˆλΉ„λΌ μžˆμ„ λ•ŒλŠ” 맀핑을 λ³€κ²½ν•˜λŠ” 게 κ°€λŠ₯ν•˜λ‹€κ³  보μž₯λœλ‹€. μŠ€μ™‘ 곡간이 μ˜ˆλΉ„λΌ μžˆμ§€ μ•Šμ„ λ•ŒλŠ” μ‚¬μš© κ°€λŠ₯ν•œ 물리적 λ©”λͺ¨λ¦¬κ°€ μ—†μœΌλ©΄ μ“°κΈ° μ‹œ SIGSEGVλ₯Ό 받을 μˆ˜λ„ μžˆλ‹€. proc(5)의 /proc/sys/vm/overcommit_memory 파일 λ…Όμ˜λ„ μ°Έκ³ ν•˜λΌ. 2.6 μ „μ˜ μ»€λ„μ—μ„œλŠ” λΉ„κ³΅μœ  μ“°κΈ° κ°€λŠ₯ λ§€ν•‘μ—λ§Œ 이 ν”Œλž˜κ·Έκ°€ νš¨κ³Όκ°€ μžˆμ—ˆλ‹€.
MAP_POPULATE (λ¦¬λˆ…μŠ€ 2.5.46λΆ€ν„°)
맀핑에 λŒ€ν•œ νŽ˜μ΄μ§€ ν…Œμ΄λΈ”μ„ μ±„μš΄λ‹€ (미리 폴트). 파일 맀핑인 경우 νŒŒμΌμ—μ„œ 미리 읽기λ₯Ό ν•˜κ²Œ ν•œλ‹€. 이후 νŽ˜μ΄μ§€ ν΄νŠΈμ—μ„œ λ§‰νžˆλŠ” κ±Έ μ€„μ΄λŠ” 데 도움이 될 것이닀. λΉ„κ³΅μœ  λ§€ν•‘μ—λŠ” λ¦¬λˆ…μŠ€ 2.6.23λΆ€ν„° MAP_POPULATEλ₯Ό μ§€μ›ν•œλ‹€.
MAP_STACK (λ¦¬λˆ…μŠ€ 2.6.27λΆ€ν„°)
ν”„λ‘œμ„ΈμŠ€λ‚˜ μŠ€λ ˆλ“œ μŠ€νƒμ— μ ν•©ν•œ μ£Όμ†Œμ— 맀핑을 ν• λ‹Ήν•œλ‹€. 이 ν”Œλž˜κ·ΈλŠ” ν˜„μž¬ no-opμ§€λ§Œ glibc μŠ€λ ˆλ”© κ΅¬ν˜„μ—μ„œ μ‚¬μš©ν•˜λŠ”λ°, 일뢀 μ•„ν‚€ν…μ²˜μ—μ„œ μŠ€νƒ 할당에 νŠΉλ³„ν•œ 처리λ₯Ό μš”ν•˜λŠ” 경우 λ‚˜μ€‘μ— 투λͺ…ν•˜κ²Œ 지원을 κ΅¬ν˜„ν•  수 있기 μœ„ν•΄μ„œλ‹€.
MAP_SYNC (λ¦¬λˆ…μŠ€ 4.15λΆ€ν„°)

이 ν”Œλž˜κ·ΈλŠ” MAP_SHARED_VALIDATE λ§€ν•‘ μœ ν˜•μ—λ§Œ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. MAP_SHARED μœ ν˜• λ§€ν•‘μ—μ„œλŠ” 이 ν”Œλž˜κ·Έλ₯Ό 쑰용히 λ¬΄μ‹œν•œλ‹€. DAX(μ˜μ† λ©”λͺ¨λ¦¬ 직접 λ§€ν•‘) 지원 νŒŒμΌμ—μ„œλ§Œ 이 ν”Œλž˜κ·Έλ₯Ό μ§€μ›ν•œλ‹€. κ·Έλ ‡μ§€ μ•Šμ€ νŒŒμΌμ—μ„œ 이 ν”Œλž˜κ·Έλ‘œ 맀핑을 λ§Œλ“€λ €κ³  ν•˜λ©΄ EOPNOTSUPP 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

이 ν”Œλž˜κ·Έλ₯Ό μ“΄ 곡유 파일 λ§€ν•‘μ—μ„œλŠ” ν”„λ‘œμ„ΈμŠ€ μ£Όμ†Œ 곡간에 μ–΄λ–€ λ©”λͺ¨λ¦¬κ°€ μ“°κΈ° κ°€λŠ₯ν•˜κ²Œ λ§΅ λ˜μ–΄ μžˆλŠ” λ™μ•ˆμ— μ‹œμŠ€ν…œμ΄ μ£½κ±°λ‚˜ μž¬λΆ€νŒ… 된 후에도 동일 파일의 동일 μ˜€ν”„μ…‹μ—μ„œ κ·Έ λ‚΄μš©μ„ λ³Ό 수 μžˆλ‹€κ³  보μž₯λœλ‹€. μ μ ˆν•œ CPU μΈμŠ€νŠΈλŸ­μ…˜κ³Ό ν•¨κ»˜ μ‚¬μš©ν•˜λ©΄ 더 효율적인 λ°©μ‹μœΌλ‘œ 데이터 변경을 μ˜μ†μ‹œν‚€λŠ” 맀핑이 κ°€λŠ₯ν•΄μ§„λ‹€.

MAP_UNINITIALIZED (λ¦¬λˆ…μŠ€ 2.6.33λΆ€ν„°)
읡λͺ… νŽ˜μ΄μ§€ λ‚΄μš©μ„ λΉ„μš°μ§€ μ•ŠλŠ”λ‹€. 이 ν”Œλž˜κ·ΈλŠ” μž„λ² λ””λ“œ μž₯μΉ˜μ—μ„œ μ„±λŠ₯을 κ°œμ„ ν•˜κΈ° μœ„ν•œ 것이닀. 컀널이 CONFIG_MMAP_ALLOW_UNINITIALIZED μ˜΅μ…˜μœΌλ‘œ κ΅¬μ„±λœ κ²½μš°μ—λ§Œ 이 ν”Œλž˜κ·Έλ₯Ό λ”°λ₯Έλ‹€. λ³΄μ•ˆμ  ν•¨μ˜ λ•Œλ¬Έμ— 보톡 μž„λ² λ””λ“œ μž₯μΉ˜μ—μ„œλ§Œ (즉 μ‚¬μš©μž λ©”λͺ¨λ¦¬ λ‚΄μš©λ¬Όμ— μ™„μ „ν•œ ν†΅μ œκ°€ μ΄λ€„μ§€λŠ” μž₯μΉ˜μ—μ„œλ§Œ) 이 μ˜΅μ…˜μ„ μΌ λ‹€.

μœ„ ν”Œλž˜κ·Έλ“€ 쀑 MAP_FIXED만 POSIX.1-2001 및 POSIX.1-2008에 λͺ…μ„Έλ˜μ–΄ μžˆλ‹€. ν•˜μ§€λ§Œ λ§Žμ€ μ‹œμŠ€ν…œμ—μ„œ MAP_ANONYMOUS도 (λ˜λŠ” λ™μ˜μ–΄μΈ MAP_ANON을) μ§€μ›ν•œλ‹€.

mmap()으둜 λ§΅ ν•œ λ©”λͺ¨λ¦¬λŠ” fork(2)λ₯Ό 거치며 같은 μ†μ„±μœΌλ‘œ μœ μ§€λœλ‹€.

νŒŒμΌμ€ νŽ˜μ΄μ§€ 크기의 배수둜 λ§΅ λœλ‹€. 파일 크기가 νŽ˜μ΄μ§€ 크기의 λ°°μˆ˜κ°€ μ•„λ‹Œ 경우 λ§΅ ν•  λ•Œ λ‚˜λ¨Έμ§€ λ©”λͺ¨λ¦¬λ₯Ό 0으둜 μ±„μš°λ©° κ·Έ μ˜μ—­μ— μ“΄ 것이 νŒŒμΌμ— κΈ°λ‘λ˜μ§€ μ•ŠλŠ”λ‹€. λ§€ν•‘ 기반 파일의 크기가 λ°”λ€” λ•Œ νŒŒμΌμ— μΆ”κ°€λ˜κ±°λ‚˜ μ œκ±°λ˜λŠ” μ˜μ—­μ— λŒ€μ‘ν•˜λŠ” νŽ˜μ΄μ§€λ“€μ— μ–΄λ–€ 영ν–₯을 μ£ΌλŠ”μ§€λŠ” λͺ…μ„Έλ˜μ–΄ μžˆμ§€ μ•Šλ‹€.

munmap()

munmap() μ‹œμŠ€ν…œ ν˜ΈμΆœμ€ μ§€μ •ν•œ μ£Όμ†Œ λ²”μœ„μ— λŒ€ν•œ 맀핑을 μ‚­μ œν•˜κ³  κ·Έ λ²”μœ„ λ‚΄ μ£Όμ†Œμ— λŒ€ν•œ 이후 μ°Έμ‘°κ°€ λΉ„μœ νš¨ λ©”λͺ¨λ¦¬ μ°Έμ‘°λ₯Ό μΌμœΌν‚€λ„λ‘ ν•œλ‹€. ν”„λ‘œμ„ΈμŠ€κ°€ μ’…λ£Œν•  λ•Œλ„ μžλ™μœΌλ‘œ ν•΄μ œν•œλ‹€. 반면 파일 λ””μŠ€ν¬λ¦½ν„°λ₯Ό λ‹«λŠ” κ²ƒμœΌλ‘œλŠ” 맡을 ν•΄μ œν•˜μ§€ μ•ŠλŠ”λ‹€.

μ£Όμ†Œ addr은 νŽ˜μ΄μ§€ 크기의 λ°°μˆ˜μ—¬μ•Ό ν•œλ‹€. (lengthλŠ” 그럴 ν•„μš”κ°€ μ—†λ‹€.) μ§€μ •ν•œ λ²”μœ„μ˜ 일뢀라도 담은 λͺ¨λ“  νŽ˜μ΄μ§€λ“€μ΄ ν•΄μ œλ˜λ©° 이후 κ·Έ νŽ˜μ΄μ§€λ“€μ— λŒ€ν•œ μ°Έμ‘°κ°€ SIGSEGVλ₯Ό μΌμœΌν‚€κ²Œ λœλ‹€. μ§€μ •ν•œ λ²”μœ„ μ•ˆμ— λ§΅ 된 νŽ˜μ΄μ§€κ°€ 없더라도 였λ₯˜κ°€ μ•„λ‹ˆλ‹€.

RETURN VALUE

성곡 μ‹œ mmap()은 λ§΅ ν•œ μ˜μ—­μ— λŒ€ν•œ 포인터λ₯Ό λ°˜ν™˜ν•œλ‹€. 였λ₯˜ μ‹œ MAP_FAILED κ°’(즉 (void *) -1)을 λ°˜ν™˜ν•˜λ©° 였λ₯˜ 원인을 λ‚˜νƒ€λ‚΄λ„λ‘ errnoλ₯Ό μ„€μ •ν•œλ‹€.

성곡 μ‹œ munmap()은 0을 λ°˜ν™˜ν•œλ‹€. μ‹€νŒ¨ μ‹œ -1을 λ°˜ν™˜ν•˜λ©° 였λ₯˜ 원인(μ•„λ§ˆ EINVAL)을 λ‚˜νƒ€λ‚΄λ„λ‘ errnoλ₯Ό μ„€μ •ν•œλ‹€.

ERRORS

EACCES
파일 λ””μŠ€ν¬λ¦½ν„°κ°€ λΉ„μ •κ·œ νŒŒμΌμ„ 가리킀고 μžˆλ‹€. λ˜λŠ” 파일 맀핑을 μš”μ²­ν–ˆλŠ”λ° fdκ°€ 읽기 κ°€λŠ₯ν•˜κ²Œ μ—΄λ € μžˆμ§€ μ•Šλ‹€. λ˜λŠ” MAP_SHAREDλ₯Ό μš”μ²­ν–ˆκ³  PROT_WRITEκ°€ 섀정돼 μžˆλŠ”λ° fdκ°€ 읽기/μ“°κΈ° λͺ¨λ“œ(O_RDWR)둜 μ—΄λ € μžˆμ§€ μ•Šλ‹€. λ˜λŠ” PROT_WRITEκ°€ 섀정돼 μžˆλŠ”λ° 파일이 λ§λΆ™μž„ μ „μš©μ΄λ‹€.
EAGAIN
파일이 잠겨 μžˆκ±°λ‚˜ λ„ˆλ¬΄ λ§Žμ€ λ©”λͺ¨λ¦¬κ°€ 고정돼 μžˆλ‹€. (setrlimit(2) μ°Έκ³ .)
EBADF
fdκ°€ μœ νš¨ν•œ 파일 λ””μŠ€ν¬λ¦½ν„°κ°€ μ•„λ‹ˆλ‹€. (그리고 MAP_ANONYMOUSλ₯Ό μ„€μ •ν•˜μ§€ μ•Šμ•˜λ‹€.)
EEXIST
flags에 MAP_FIXED_NOREPLACEλ₯Ό μ§€μ •ν–ˆμœΌλ©° addrκ³Ό lengthκ°€ λ‚˜νƒ€λ‚΄λŠ” λ²”μœ„κ°€ κΈ°μ‘΄ λ§€ν•‘κ³Ό μΆ©λŒν•œλ‹€.
EINVAL
addr, length, offset이 λ§ˆμŒμ— λ“€μ§€ μ•ŠλŠ”λ‹€. (κ°€λ Ή λ„ˆλ¬΄ ν¬κ±°λ‚˜ νŽ˜μ΄μ§€ 경계에 정렬돼 μžˆμ§€ μ•Šλ‹€.)
EINVAL
(λ¦¬λˆ…μŠ€ 2.6.12λΆ€ν„°) lengthκ°€ 0이닀.
EINVAL
flags에 MAP_PRIVATEκ³Ό MAP_SHARED μ–΄λŠ μͺ½λ„ μ—†κ±°λ‚˜ λ‘˜ λ‹€ 포함돼 μžˆλ‹€.
ENFILE
μ—΄λ¦° 파일 μ΄κ°œμˆ˜μ— λŒ€ν•œ μ‹œμŠ€ν…œ μ „μ—­ μ œν•œμ— λ„λ‹¬ν–ˆλ‹€.
ENODEV
μ§€μ •ν•œ 파일의 기반 파일 μ‹œμŠ€ν…œμ΄ λ©”λͺ¨λ¦¬ 맀핑을 μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€.
ENOMEM
μ‚¬μš© κ°€λŠ₯ν•œ λ©”λͺ¨λ¦¬κ°€ μ—†λ‹€.
ENOMEM
ν”„λ‘œμ„ΈμŠ€μ˜ λ§€ν•‘ μ΅œλŒ€ 개수λ₯Ό μ΄ˆκ³Όν•˜λ € ν–ˆλ‹€. munmap()μ—μ„œλ„ 이 였λ₯˜κ°€ λ°œμƒν•  수 μžˆλŠ”λ°, κΈ°μ‘΄ λ§€ν•‘μ˜ 쀑간 뢀뢄을 λ§΅ ν•΄μ œν•˜λ©΄ κ·Έ μ–‘μͺ½μœΌλ‘œ μž‘μ€ λ§€ν•‘ 두 κ°œκ°€ 생기기 λ•Œλ¬Έμ΄λ‹€.
ENOMEM
(λ¦¬λˆ…μŠ€ 4.7λΆ€ν„°) ν”„λ‘œμ„ΈμŠ€μ˜ RLIMIT_DATA μ œν•œ(getrlimit(2)μ—μ„œ μ„€λͺ…함)을 μ΄ˆκ³Όν•˜λ € ν–ˆλ‹€.
EOVERFLOW
32λΉ„νŠΈ μ•„ν‚€ν…μ²˜μ— 큰 파일 ν™•μž₯(즉 64λΉ„νŠΈ off_t)을 μ“°λŠ” 경우: lengthλ₯Ό μœ„ν•œ νŽ˜μ΄μ§€ κ°œμˆ˜μ— offset을 μœ„ν•œ νŽ˜μ΄μ§€ 개수λ₯Ό λ”ν•˜λ©΄ unsigned long(32λΉ„νŠΈ)을 λ„˜κ²Œ λœλ‹€.
EPERM
prot μΈμžμ—μ„œ PROT_EXECλ₯Ό μš”μ²­ν•˜λŠ”λ° λ§΅ μ˜μ—­μ΄ μ‹€ν–‰ λΆˆκ°€λŠ₯ν•˜κ²Œ 마운트 된 파일 μ‹œμŠ€ν…œ μƒμ˜ νŒŒμΌμ— 속해 μžˆλ‹€.
EPERM
파일 봉인 λ•Œλ¬Έμ— λ™μž‘μ΄ λ§‰ν˜”λ‹€. fcntl(2) μ°Έκ³ .
ETXTBSY
MAP_DENYWRITEκ°€ 섀정돼 μžˆμ§€λ§Œ fd둜 μ§€μ •ν•œ 객체가 μ“°κΈ° κ°€λŠ₯ν•˜κ²Œ μ—΄λ € μžˆλ‹€.

λ§΅ ν•œ μ˜μ—­μ„ μ‚¬μš©ν•  λ•Œ λ‹€μŒ μ‹œκ·Έλ„μ΄ λ°œμƒν•  수 μžˆλ‹€.

SIGSEGV
읽기 μ „μš©μœΌλ‘œ λ§΅ ν•œ μ˜μ—­μ— μ“°κΈ°λ₯Ό μ‹œλ„ν–ˆλ‹€.
SIGBUG
νŒŒμΌμ— λŒ€μ‘ν•˜μ§€ μ•ŠλŠ” 버퍼 뢀뢄에 접근을 μ‹œλ„ν–ˆλ‹€. (예λ₯Ό λ“€μ–΄ 파일 끝 λ„ˆλ¨Έμ— μ ‘κ·Όν•˜κΈ°. λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€κ°€ νŒŒμΌμ„ μž˜λΌλ‚΄λŠ” 경우 포함.)

ATTRIBUTES

이 μ ˆμ—μ„œ μ‚¬μš©ν•˜λŠ” μš©μ–΄λ“€μ— λŒ€ν•œ μ„€λͺ…은 attributes(7)λ₯Ό 보라.

μΈν„°νŽ˜μ΄μŠ€ 속성 κ°’
mmap(), munmap() μŠ€λ ˆλ“œ μ•ˆμ „μ„± MT-Safe

CONFORMING TO

POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD.

AVAILABILITY

mmap(), msync(2), munmap()이 μ‚¬μš© κ°€λŠ₯ν•œ POSIX μ‹œμŠ€ν…œμ—λŠ” <unistd.h>에 _POSIX_MAPPED_FILESκ°€ 0보닀 큰 κ°’μœΌλ‘œ μ •μ˜λ˜μ–΄ μžˆλ‹€. (sysconf(3)도 μ°Έκ³ .)

NOTES

일뢀 ν•˜λ“œμ›¨μ–΄ μ•„ν‚€ν…μ²˜(κ°€λ Ή i386)μ—μ„œλŠ” PROT_WRITEκ°€ PROT_READλ₯Ό ν•¨μ˜ν•œλ‹€. μ•„ν‚€ν…μ²˜μ— 따라 PROT_READκ°€ PROT_EXECλ₯Ό ν•¨μ˜ν•˜λŠ”μ§€ μ—¬λΆ€κ°€ λ‹€λ₯΄λ‹€. 이식 κ°€λŠ₯ν•œ ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” μƒˆ λ§€ν•‘ λ‚΄μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  μ˜ˆμ •μ΄λ©΄ 항상 PROT_EXECλ₯Ό μ„€μ •ν•˜λŠ” 게 μ’‹λ‹€.

맀핑을 λ§Œλ“œλŠ” 이식성 μžˆλŠ” 방법은 addr을 0(NULL)으둜 μ§€μ •ν•˜κ³  flagsμ—μ„œ MAP_FIXEDλ₯Ό λΉΌλŠ” 것이닀. μ΄λ ‡κ²Œ ν•˜λŠ” 경우 맀핑에 μ“Έ μ£Όμ†Œλ₯Ό μ‹œμŠ€ν…œμ΄ μ„ νƒν•œλ‹€. κΈ°μ‘΄ λ§€ν•‘κ³Ό μΆ©λŒν•˜μ§€ μ•ŠμœΌλ©° 0이 μ•„λ‹ˆκ²Œ μ£Όμ†Œλ₯Ό μ„ νƒν•œλ‹€. MAP_FIXED ν”Œλž˜κ·Έλ₯Ό μ§€μ •ν•˜λŠ” 경우 addr이 0(NULL)이면 λ§΅ ν•œ μ£Όμ†Œκ°€ 0(NULL)이 λœλ‹€.

μ–΄λ–€ flags μƒμˆ˜λ“€μ€ μ μ ˆν•œ κΈ°λŠ₯ 확인 λ§€ν¬λ‘œκ°€ (λ•Œλ‘  기본으둜) μ •μ˜λΌ μžˆλŠ” κ²½μš°μ—λ§Œ μ •μ˜λΌ μžˆλ‹€. glibc 2.19 및 μ΄ν›„μ—μ„œλŠ” _DEFAULT_SOURCE, glibc 2.19 및 μ΄μ „μ—μ„œλŠ” _BSD_SOURCEλ‚˜ _SVID_SOURCE이닀. (_GNU_SOURCE μ‚¬μš©μœΌλ‘œλ„ μΆ©λΆ„ν•˜λ©°, λͺ…ν™•νžˆ 이 맀크둜λ₯Ό μš”κ±΄μœΌλ‘œ ν•˜λŠ” 게 더 논리적일 μˆ˜λ„ μžˆλŠ” 것이, κ·Έ ν”Œλž˜κ·Έλ“€ λͺ¨λ‘ λ¦¬λˆ…μŠ€ μ „μš©μ΄λ‹€.) ν•΄λ‹Ήν•˜λŠ” ν”Œλž˜κ·ΈλŠ” MAP_32BIT, MAP_ANONYMOUS (및 λ™μ˜μ–΄μΈ MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE, MAP_STACK이닀.

μ‘μš©μ—μ„œ mincore(2)λ₯Ό μ‚¬μš©ν•˜λ©΄ λ§€ν•‘μ˜ μ–΄λ–€ νŽ˜μ΄μ§€κ°€ ν˜„μž¬ 버퍼/νŽ˜μ΄μ§€ μΊμ‹œμ— 상주 쀑인지 μ•Œμ•„λ‚Ό 수 μžˆλ‹€.

MAP_FIXED μ•ˆμ „ν•˜κ²Œ μ‚¬μš©ν•˜κΈ°

MAP_FIXEDλ₯Ό μ•ˆμ „ν•˜κ²Œ μ“Έ 수 μžˆλŠ” μœ μΌν•œ κ²½μš°λŠ” addrκ³Ό length둜 μ§€μ •ν•œ μ£Όμ†Œ λ²”μœ„κ°€ 이미 λ‹€λ₯Έ 맀핑을 톡해 μž‘ν˜€ μžˆμ„ λ•Œμ΄λ‹€. κ·Έ μ™Έ κ²½μš°μ—μ„œλŠ” MAP_FIXED μ‚¬μš©μ΄ 극히 μœ„ν—˜ν•œλ°, 기쑴에 있던 맀핑을 κ°•μ œλ‘œ μ—†μ• λ―€λ‘œ 닀쀑 μŠ€λ ˆλ“œ ν”„λ‘œμ„ΈμŠ€μ—μ„œ 자기 μ£Όμ†Œ 곡간을 μ˜€μ—Όμ‹œν‚€κΈ° μ‰½κ²Œ 되기 λ•Œλ¬Έμ΄λ‹€.

예λ₯Ό λ“€μ–΄ μŠ€λ ˆλ“œ Aκ°€ /proc/<pid>/mapsλ₯Ό μ‚΄νŽ΄λ΄μ„œ MAP_FIXED둜 λ§΅ ν•  수 μžˆλŠ” μ•ˆ μ“°λŠ” μ£Όμ†Œ λ²”μœ„λ₯Ό μ°ΎλŠ” λ™μ•ˆ μŠ€λ ˆλ“œ Bκ°€ λ™μ‹œμ— 같은 μ£Όμ†Œ λ²”μœ„μ˜ 일뢀 λ‚΄μ§€ 전체λ₯Ό νšλ“ν•  수 μžˆλ‹€. κ·ΈλŸ¬κ³ μ„œ μŠ€λ ˆλ“œ Aκ°€ mmap(MAP_FIXED)λ₯Ό μ‚¬μš©ν•˜λ©΄ μŠ€λ ˆλ“œ Bκ°€ λ§Œλ“  맀핑을 μ‹€μ§ˆμ μœΌλ‘œ μ†μƒμ‹œν‚€κ²Œ λœλ‹€. 이 κ²½μš°μ—μ„œ μŠ€λ ˆλ“œ Bκ°€ κΌ­ 맀핑을 직접 생성해야 ν•˜λŠ” 건 μ•„λ‹ˆλ‹€. λ‚΄λΆ€μ μœΌλ‘œ dlopen(3)을 μ¨μ„œ μ–΄λ–€ λ‹€λ₯Έ 곡유 라이브러리λ₯Ό μ μž¬ν•˜λŠ” 라이브러리 ν˜ΈμΆœμ„ ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œ μΆ©λΆ„ν•˜λ‹€. κ·Έ dlopen(3) 호좜이 라이브러리λ₯Ό ν”„λ‘œμ„ΈμŠ€μ˜ μ£Όμ†Œ κ³΅κ°„μœΌλ‘œ λ§΅ ν•˜κ²Œ λœλ‹€. 뿐만 μ•„λ‹ˆλΌ 거의 λͺ¨λ“  라이브러리 호좜이 이 κΈ°λ²•μ΄λ‚˜ λ‹¨μˆœ λ©”λͺ¨λ¦¬ 할당을 톡해 μ£Όμ†Œ 곡간에 λ©”λͺ¨λ¦¬ 맀핑을 μΆ”κ°€ν•˜λ„λ‘ κ΅¬ν˜„λ˜μ–΄ μžˆμ„ 수 μžˆλ‹€. brk(2), malloc(3), pthread_create(3), PAM 라이브러리(http://www.linux-pam.org) 등이 κ·Έ μ˜ˆμ΄λ‹€.

λ¦¬λˆ…μŠ€ 4.17λΆ€ν„°λŠ” 닀쀑 μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž¨μ—μ„œ MAP_FIXED_NOREPLACE ν”Œλž˜κ·Έλ₯Ό μ‚¬μš©ν•΄μ„œ κΈ°μ‘΄ λ§€ν•‘μœΌλ‘œ μ˜ˆμ•½λΌ μžˆμ§€ μ•Šμ€ κ³ μ • μ£Όμ†Œμ— 맀핑을 λ§Œλ“€λ € ν•  λ•Œ μœ„μ—μ„œ μ„€λͺ…ν•œ μœ„ν—˜μ„ ν”Όν•  수 μžˆλ‹€.

파일 기반 λ§€ν•‘μ—μ„œμ˜ νƒ€μž„μŠ€νƒ¬ν”„ λ³€κ²½

파일 기반 λ§€ν•‘μ—μ„œλŠ” mmap()κ³Ό λŒ€μ‘ν•˜λŠ” λ§΅ ν•΄μ œ μ‚¬μ΄μ˜ μ–΄λŠ μ‹œμ μ—λ„ λ§΅ 된 파일의 st_atime ν•„λ“œκ°€ 갱신될 수 μžˆλ‹€. λ§΅ 된 νŽ˜μ΄μ§€μ— 처음 μ°Έμ‘°ν•  λ•Œ κ·Έ ν•„λ“œκ°€ 아직 κ°±μ‹ λ˜μ§€ μ•Šμ•˜μœΌλ©΄ κ°±μ‹ ν•˜κ²Œ λœλ‹€.

PROT_WRITE 및 MAP_SHARED둜 λ§΅ ν•œ 파일의 st_ctime 및 st_mtime ν•„λ“œλŠ” λ§΅ μ˜μ—­μ— λŒ€ν•œ μ“°κΈ° 후에, 그리고 이후 MS_SYNC λ‚΄μ§€ MS_ASYNC ν”Œλž˜κ·Έλ‘œ msync(2) ν•˜λŠ” 경우 κ·Έ 전에 κ°±μ‹ λœλ‹€.

κ±°λŒ€ νŽ˜μ΄μ§€ (Huge TLB) λ§€ν•‘

κ±°λŒ€ νŽ˜μ΄μ§€λ₯Ό μ΄μš©ν•˜λŠ” λ§€ν•‘μ—μ„œλŠ” mmap()κ³Ό munmap() μΈμžμ— λŒ€ν•œ μš”κ±΄μ΄ μ‹œμŠ€ν…œ κΈ°λ³Έ νŽ˜μ΄μ§€ 크기λ₯Ό μ“°λŠ” 맀핑에 λŒ€ν•œ μš”κ±΄κ³Ό μ’€ λ‹€λ₯΄λ‹€.

mmap()μ—μ„œλŠ” offset이 기반 κ±°λŒ€ νŽ˜μ΄μ§€ 크기의 λ°°μˆ˜μ—¬μ•Ό ν•œλ‹€. μ‹œμŠ€ν…œμ—μ„œ lengthλ₯Ό 기반 κ±°λŒ€ νŽ˜μ΄μ§€ 크기의 배수둜 μžλ™μœΌλ‘œ λ§žμΆ˜λ‹€.

munmap()μ—μ„œλŠ” addrκ³Ό lengthκ°€ λͺ¨λ‘ 기반 κ±°λŒ€ νŽ˜μ΄μ§€ 크기의 λ°°μˆ˜μ—¬μ•Ό ν•œλ‹€.

C 라이브러리/컀널 차이

이 νŽ˜μ΄μ§€μ—μ„œλŠ” glibc의 mmap() 래퍼 ν•¨μˆ˜κ°€ μ œκ³΅ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό κΈ°μˆ ν•œλ‹€. μ›λž˜λŠ” κ·Έ ν•¨μˆ˜μ—μ„œ 이름이 같은 μ‹œμŠ€ν…œ ν˜ΈμΆœμ„ λΆˆλ €λ‹€. 컀널 2.4λΆ€ν„° κ·Έ μ‹œμŠ€ν…œ 호좜이 mmap2(2)둜 λŒ€μ²΄λκ³ , κ·Έλž˜μ„œ μš”μ¦˜μ—λŠ” glibc의 mmap() 래퍼 ν•¨μˆ˜μ—μ„œ 적절히 μ‘°μ •ν•œ offset κ°’μœΌλ‘œ mmap2(2)λ₯Ό λΆ€λ₯Έλ‹€.

BUGS

λ¦¬λˆ…μŠ€μ—μ„œλŠ” μœ„μ˜ MAP_NORESERVEμ—μ„œ μ–ΈκΈ‰ν•˜λŠ” 것듀을 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€. 기본적으둜 μ‹œμŠ€ν…œμ— λ©”λͺ¨λ¦¬κ°€ λΆ€μ‘±ν•  λ•ŒλŠ” μ–Έμ œ μ–΄λŠ ν”„λ‘œμ„ΈμŠ€λ“  죽을 수 μžˆλ‹€.

컀널 2.6.7 μ „μ—μ„œλŠ” protλ₯Ό PROT_NONE으둜 μ§€μ •ν•œ κ²½μš°μ—λ§Œ MAP_POPULATE ν”Œλž˜κ·Έμ— 효λ ₯이 μžˆλ‹€.

SUSv3μ—μ„œλŠ” lengthκ°€ 0이면 mmap()이 μ‹€νŒ¨ν•˜λŠ” 게 μ’‹λ‹€κ³  λͺ…μ„Έν•œλ‹€. ν•˜μ§€λ§Œ 컀널 2.6.12 μ „μ—μ„œλŠ” 이 κ²½μš°μ— mmap()이 μ„±κ³΅ν–ˆλ‹€. 아무 맀핑도 λ§Œλ“€μ§€ μ•Šκ³  호좜이 addr을 λ°˜ν™˜ν–ˆλ‹€. 컀널 2.6.12λΆ€ν„°λŠ” 이 κ²½μš°μ— mmap()이 EINVAL 였λ₯˜λ‘œ μ‹€νŒ¨ν•œλ‹€.

POSIXμ—μ„œλŠ” 객체 끝의 λΆ€λΆ„ νŽ˜μ΄μ§€λ₯Ό 항상 μ‹œμŠ€ν…œμ—μ„œ 0으둜 μ±„μ›Œμ•Ό ν•˜λ©° 객체 끝 λ„ˆλ¨Έμ—μ„œμ˜ λ³€κ²½ λ‚΄μš©μ„ μ‹œμŠ€ν…œμ΄ μ ˆλŒ€ κΈ°λ‘ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  λͺ…μ„Έν•œλ‹€. λ¦¬λˆ…μŠ€μ—μ„œ 그런 객체 끝 λ‹€μŒμ˜ λΆ€λΆ„ νŽ˜μ΄μ§€μ— 데이터λ₯Ό μ“°λŠ” 경우 파일이 λ‹«νžˆκ³  맡이 ν•΄μ œλœ 후에 μ ˆλŒ€ νŒŒμΌμ—λŠ” κΈ°λ‘λ˜μ§€ μ•Šμ§€λ§Œ 데이터가 νŽ˜μ΄μ§€ μΊμ‹œ 내에 λ‚¨μ•„μ„œ 이후 λ§€ν•‘μ—μ„œ κ·Έ λ³€κ²½λœ λ‚΄μš©μ„ λ³Ό μˆ˜λ„ μžˆλ‹€. μ–΄λ–€ κ²½μš°μ—λŠ” λ§΅ ν•΄μ œ 전에 msync(2)λ₯Ό ν˜ΈμΆœν•΄μ„œ κ³ μΉ  μˆ˜λ„ μžˆμ§€λ§Œ tmpfs(5)μ—μ„œλŠ” (예λ₯Ό λ“€μ–΄ shm_overview(7)에 기둝된 POSIX 곡유 λ©”λͺ¨λ¦¬ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ“Έ λ•ŒλŠ”) ν†΅ν•˜μ§€ μ•ŠλŠ”λ‹€.

EXAMPLE

λ‹€μŒ ν”„λ‘œκ·Έλž¨μ€ 첫 번째 λͺ…λ Ήν–‰ μΈμžμ— μ§€μ •ν•œ 파일의 일뢀λ₯Ό ν‘œμ€€ 좜λ ₯으둜 μ°λŠ”λ‹€. 두 λ²ˆμ§Έμ™€ μ„Έ 번째 λͺ…λ Ήν–‰ 인자의 μ˜€ν”„μ…‹ 및 길이 값을 톡해 찍을 λ²”μœ„λ₯Ό μ§€μ •ν•œλ‹€. ν”„λ‘œκ·Έλž¨μ—μ„œ 파일의 ν•„μš”ν•œ νŽ˜μ΄μ§€λ“€λ‘œ λ©”λͺ¨λ¦¬ 맀핑을 λ§Œλ“  λ‹€μŒ write(2)λ₯Ό μ¨μ„œ μ›ν•˜λŠ” λ°”μ΄νŠΈλ“€μ„ 좜λ ₯ν•œλ‹€.

ν”„λ‘œκ·Έλž¨ μ†ŒμŠ€

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

int
main(int argc, char *argv[])
{
    char *addr;
    int fd;
    struct stat sb;
    off_t offset, pa_offset;
    size_t length;
    ssize_t s;

    if (argc < 3 || argc > 4) {
        fprintf(stderr, "%s file offset [length]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    fd = open(argv[1], O_RDONLY);
    if (Fd == -1)
        handle_error("open");

    if (fstat(fd, &sb) == -1)           /* 파일 크기 μ–»κΈ° */
        handle_error("fstat");

    offset = atoi(argv[2]);
    pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
        /* mmap() μ˜€ν”„μ…‹μ΄ νŽ˜μ΄μ§€μ— 정렬돼 μžˆμ–΄μ•Ό 함 */

    if (offset >= sb.st_size) {
        fprintf(stderr, "offset is past end of file\n");
        exit(EXIT_FAILURE);
    }

    if (argc == 4) {
        length = atoi(argv[3]);
        if (offset + length > sb.st_size)
            length = sb.st_size - offset;
                /* 파일 끝 λ„ˆλ¨Έμ˜ λ°”μ΄νŠΈλŠ” ν‘œμ‹œν•  수 μ—†μŒ */

    } else {    /* length 인자 μ—†μŒ ==> 파일 λκΉŒμ§€ ν‘œμ‹œ */
        length = sb.st_size - offset;
    }

    addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
                MAP_PRIVATE, fd, pa_offset);
    if (addr == MAP_FAILED)
        handle_error("mmap");

    s = write(STDOUT_FILENO, addr + offset - pa_offset, length);
    if (s != length) {
        if (s == -1)
            handle_error("write");

        fprintf(stderr, "partial write");
        exit(EXIT_FAILURE);
    }

    munmap(addr, length + offset - pa_offset);
    close(fd);

    exit(EXIT_SUCCESS);
}

SEE ALSO

ftruncate(2), getpagesize(2), memfd_create(2), mincore(2), mlock(2), mmap2(2), mprotect(2), mremap(2), msync(2), remap_file_pages(2), setrlimit(2), shmat(2), userfaultfd(2), shm_open(3), shm_overview(7)

proc(5) λ‚΄μ˜ /proc/[pid]/maps, /proc/[pid]/map_files, /proc/[pid]/smaps νŒŒμΌμ— λŒ€ν•œ μ„€λͺ….

B.O. Gallmeister, POSIX.4, O'Reilly, 128-129μͺ½ 및 389-391μͺ½.


2019-02-27

⚠️ **GitHub.com Fallback** ⚠️