9.8 Memory Mapping
Linux는 disk에 있는 어떠한 object를 매핑함으로써 virtual memory 영역을 초기화 할 수 있는데, 이러한 기법을 memory mapping이라고 한다. 매핑되는 obejct로는 다음 두가지가 있다.
- Regular file(in the Linux file system)
- virtual memory 영역은 executable object file과 같은, 연속적인 section의 regular disk file에 mapping 될 수 있다.
- 각 file section들은 page크기로 나눠지고
- 각 나눠진 조각들은 virtual mameory를 이루는 virtual page들 각각의 초기 값이 된다.
- demand paging으로 인해, 이 virtual page들은 CPU가 처음 ‘touch’ 하기 전까진 실제로 physical memory로 swap 되지 않는다.
- 만약 매핑되는 영역의 크기가 각 file section의 크기보다 크다면, 나머지 공간은 0으로 채워진다.
- virtual memory 영역은 executable object file과 같은, 연속적인 section의 regular disk file에 mapping 될 수 있다.
- Anonymous file
- virtual memory 영역은 또한 kernel에 의해 생성된 anonymous file에도 mapping될 수 있다.
- 이 anonymous file은 0으로 꽉 채워져 있는 file을 말한다.
- 처음 CPU가 해당 영역에 있는 virtual page를 ‘touch’ → kernel은 physical memory에서 적절한 victim page를 찾아냄 → 이 victim이 swap out하고, dirty bit라면 victim page를 0으로 채움 → 이후 page table을 현재 CPU가 touch한 page로 update함
- 눈여겨 봐야할 점은, 어떠한 data도 disk와 memory 사이에서 전송이 일어나지 않은 것이다.
- 이러한 이유로, anonymous file에 mapping된 영역 안의 page들은 demand-zero page 라고 부르기도 한다.
- virtual memory 영역은 또한 kernel에 의해 생성된 anonymous file에도 mapping될 수 있다.
두 case들은, 한번 virtual page가 초기화 되면, kernel이 유지하고 있는 swap file 사이에서 swapped 되거나 swap한다.
중요한 것은, 이러한 swap file들이 현재 실행중인 프로세스에 의해 할당된 virtual page들의 총 량을 제한한다는 것이다.
9.8.1 Shared Objects Revisited
기존 file system과 virtual memory system을 통합하여 더 간단하고 효율적으로 program과 data를 메모리에 load할 수 있게 되었다.
- 각 process가 bash program에 대한 process라면, 모두 같은 code를 실행하게 될 것이다.
- printf를 사용하는 모든 process에서는 모두 동일한 run-time 라이브러리 code들에 접근한다.
이런 중복되는 것들을 모두 각각 가지고 있다면 매우 공간적인 낭비가 심할 것이다. 이에 memory-mapping이 어떻게 이런 공유되는 object들을 control하는지를 살펴볼 것이다.
위 문제를 control 하는 매커니즘
- mapping될 수 있는 object로는 shared object와 private object가 있다.
- shared object
- 여러 프로세스가 하나의 shared object에 매핑되고 있을 때, 하나의 process가 write를 수행한다면?
- 전부 visible하다.(모든 process에 반영된다)
- 또한 disk에도 이 write가 반영된다.
- private object
- 하나의 write는 다른 process에선 not visible하다.
- 또한 disk에도 반영이 되지 않는다.
- 이렇게 각 object들에 mapping되는 virtual memory 영역을 각각 shared area , private area 라고 한다.
shared object

- 각 object에 대한 filename은 고유하므로, kernel이 process1에서 이미 object와 mapping되어 있는 것을 확인할 수 있다.
- 따라서 process2에게 적절한 physical page들을 가리키게 할 수 있다.
- 중요한 점
- physical memory에 오직 하나의 shared object의 복사본만 저장된다.
private object

- private object도 마찬가지로 처음 시작은 shared object와 같다. 즉, 하나의 private object의 복사본만 physical memory에 저장된다.
- 이 때, private object를 매핑하고 있는 각 process들에서, private area에 해당하는 PTE들은 모두 read-only 로 flag 처리 된다.
- 또한 area struct도 private copy-on-write 로 flag 처리 된다.
- TODO: area struct가 뭔가? → 9.7장 확인할 것
- 이에 따라 process가 각각의 private area에 쓰기를 시도하지만 않는다면, physical memory에서는 복사본 하나로 계속 유지된다.
- 만약 이러한 private area에 해당하는 page에 write를 시도하게 된다면?
- protection fault가 발생한다. → fault handler에게 control이 넘어가게 된다.
- fault handler는 private copy-on-write area에 있는 page에 write를 시도한 것에 의해 발생되었다는 것을 알아차리고,
- physical memory에 새로운 복사본을 만들어서, page table entry를 update함으로서 새로운 복사본을 가리키게 하도록 한다.
- 이 page에 경우, write 권한을 복구시켜준다.
- fault handler가 반환되면, CPU는 다시 write를 실행시키고, 이에 새로 생성된 page에 대해 write가 수행된다.
- 이러한 매커니즘을 private copy-on-write 매커니즘이라고 한다.
9.8.2 The fork Function Revisited
fork 함수는 독립적인 virtual addres space와 함께 새로운 process를 생성한다. 어떻게 이런 동작을 수행하는지를 memory mapping idea로 설명해보자.
- fork 함수가 현재 process에서 호출된다.
- kernel은 새로운 process를 위한 다양한 data structure(page table, open file table 등등)들을 생성한다.
- 그리고 고유한 PID를 할당한다.
- 새로운 process의 virtual meory를 생성하기 위해
- 현재 process의 mm_struct 와 area struct, 그리고 page table들의 똑같은 복사본을 생성한다.
- 그리고 두 process모두에게서 이 page들을 read-only 로 flag처리한다.
- 또한 마찬가지로 각 area struct도 private copy-on-write로 flag처리한다.
- fork가 반환되면, 새로운 process는 virtual memory의 완전한 복사본을 갖게 된다.
- 이후 여러번의 write가 수행된다면, copy-on-write 매커니즘이 새로운 page를 생성하고, 이에 따라 private address space의 추상화를 보존할 수 있도록 한다.
9.8.3 The execve Function Revisited
memory mapping은 program들을 memory로 loading하는데에도 중요한 역할을 한다. 이제 execve가 어떻게 program을 load하고 실행하는지를 살펴보자.

execve("a.out", NULL, NULL);
- executable object file인 “a.out” file을 위와 같이 실행시키려 한다.
- 이에 a.out program으로 현재 프로그램이 교체된다
- 이 때 다음의 step을 따른다.
- 현재 user area들을 삭제한다.(user 영역에 있는 area struct들을 전부 지운다.)
- 새로운 area struct들을 생성한다.(code, data, bss, stack영역)
- 이들은 전부 private copy-on-write이다.
- code와 data 영역: a.out file에서의 .text와 .data 영역에 mapping되고
- bss영역 : demand-zero(anonymous file에 매핑된 것)
- stack & heap 영역 : 마찬가지로 demand-zero이다.
- shared area들을 mapping시킨다.
- 만약 a.out program이 shared object에 link 되어있다면, 이 object들은 동적으로 이 program에 link된다.
- 이후 user의 virtual address space의 shared 구역에 mapping된다.
- PC를 설정한다.
- 현재 process의 context에서의 program counter를 code 영역의 entry point를 가리키도록 세팅한다.
- 이후에 이 process가 스케쥴 되면, 해당 설정된 entry point에서부터 실행이 시작될 것이다.
- Linux는 code와 data영역의 page들을 필요할 때마다 swap할 것이다.
9.8.4 User-Level Memory Mapping with the mmap Function
Linux process들은 virtual memory의 새로운 영역을 생성하고, 해당 영역들에 object들을 mapping하도록 하는 mmap 함수를 사용할 수 있다.

- mmap 인자
- start : kernel한테 새 virtual memory 영역을 생성할 때, 이곳에서 시작하는 것을 더 선호한다고 요청할 수 있다. 하지만 단지 hint일 뿐, 반드시 여기서 시작한다고 보장할 순 없다. (보통 NULL을 집어넣는다고 함)
- fd : fd에 해당하는 file에 대한 object에서의 연속적인 chunk를 mapping하도록 할 수 있다.
- length : 이 chunk는 length만큼의 byte 크기를 가진다.
- offset : 또한 이 chunk가 fd로 명시한 file에서의 offset에서부터 시작한다는 것을 명시할 수 있다.
- prot : 새로 mapping된 virtual memory 영역의 접근 권한을 설명하는 bit이다.
- PROT_EXEC : 이 영역에 있는 page들은 CPU에 의해 실행될 수 있는 instruction들로 구성되어져 있다.
- PROT_READ : read할 수 있다.
- PROT_WRITE : 이 영역의 page에 write할 수 있다.
- PROT_NONE : 이 영역에 있는 page에는 접근할 수 없다.
- flags : mapping된 object의 type을 설명하는 bit이다.
- MAP_ANON flag : object가 anonymous이다. → virtual page들은 demand-zero이다.
- MAP_PRIVATE : private copy-on-write object임을 나타낸다.
- MAP_SHARED : shared object임을 나타낸다.
- munmap 함수
- start 주소로부터 시작하는 영역을 legnth byte만큼 삭제한다.
- 만약 이후에 이 삭제된 영역을 참조한다면 이는 segmentation fault를 야기한다.
'Computer Science > 컴퓨터 구조' 카테고리의 다른 글
[CSAPP] 4.1 The Y86-64 Instruction Set Architecture (0) | 2023.03.01 |
---|---|
[CSAPP] 9.7 Case Study: The Intel Core i7 / Linux Memory System (0) | 2023.03.01 |
[CSAPP] 8.3 System Call Error Handling (시스템 콜 에러 처리) (0) | 2023.03.01 |
[CSAPP] 8.2 Processes (프로세스) (0) | 2023.03.01 |
[CSAPP] 9.3 VM as a Tool for Caching(캐싱 도구로서의 VM) (0) | 2023.03.01 |