현재의 PintOS는 mmap()과 munmap() 함수가 구현되어 있지 않기 때문에 요구 페이징에 의해 파일 데이터를 메모리로 로드하는 mmap() 함수와 파일 맵핑을 제거하는 munmap() 함수를 구현해야 한다.
파일의 입출력을 페이지에 존재하는 디스크 블록에 맵핑에 의한 메모리 접근으로 생각한다.
파일은 요구 페이징에 의해 가장 먼저 읽힌다.
파일에 대한 접근을 read()나 write() 시스템 콜이 아닌 메모리를 통한 파일 입출력으로 생각한다.
여러 프로세스가 메모리의 페이지들을 공유하여 같은 파일을 사용할 수 있도록 한다.
기본적인 메커니즘은 프로세스 A와 프로세스 B의 가상 메모리에서 물리 메모리에 접근하여 같은 파일을 사용한다. (추측)
프로세스 1의 공유 메모리와 프로세스 2의 공유 메모리를 사용하여 memory-mapped file을 생성한다. (추측)
입출력 장치에 보다 편리한 접근을 가능하기 위해 많은 컴퓨터 시스템 설계자들은 메모리-맵핑 입출력을 제공한다.
이러한 경우 메모리 주소들이 준비되어야 한다.
장치 레지스터로부터 데이터가 전송되어야 하기 때문에 메모리 주소들을 읽고 쓴다.
빠른 응답 시간을 필요로 하는 장치들에 사용하기 적합하다.
fd: 프로세스의 가상 주소공간에 맵핑할 파일
addr: 맵핑을 시작할 주소 (페이지 단위 정렬)
성공 시 mapping id를 리턴하고, 실패 시 에러코드(-1)을 리턴한다.
요구 페이징에 의해 파일 데이터를 메모리로 로드한다.
프로세스 주소공간에 파일을 맵핑한다.
read/write 시스템 콜을 사용하는 대신 메모리 접근 함수(load/store)을 통해 파일을 접근한다.
mmap(int fd, void *addr)
vm_entry를 생성한다.
vm_entry를 hash_insert()하여 해시 테이블(thread 구조체의 vm)에 삽입한다.
인자로 입력된 addr로 프로세스 가상 주소로부터 요구 페이징한다.
thread 구조체에 mmap_list라는 멤버를 추가하여 mmap_file 구조체의 정보를 포함하고 vm_entry를 통해 프로세스 주소공간에 접근하여 블록 장치의 메모리-맵핑 파일들을 사용한다.
struct mmap_file 구조체를 생성하여 맵핑된 파일의 정보를 저장한다.
mapid: mmap() 성공 시 리턴된 mapping id
file: 맵핑하는 파일의 파일 오브젝트
elem: mmap_file들의 리스트 연결을 위한 구조체
vme_list: mmap_file에 해당하는 모든 vm_entry들의 리스트
thread 구조체의 해시 테이블 vm에서는 vm_entry의 elem 필드를 사용한다.
mmap_file의 리스트 헤드 vme_list는 vm_entry의 mmap_elem 필드를 사용한다.
해시 테이블 vm은 buckets 필드를 가지며 vm_entry가 어떤 bucket에 저장되어 있는지 나타낸다.
mmap_list에서 해제할 mmap_file을 검색한다.
vme_list 내의 모든 vm_entry를 해제한다.
mmap_file을 해제한다.
munmap() 함수는 mmap_list에서 해제할 mmap_file을 검색하여 vme_list 내의 모든 vm_entry를 해제하고 마지막으로 mmap_file을 해제한다.
mmap() 함수는 인자로 입력 받은 addr가 유효한지 확인하고 file_reopen()을 실행하여 mapid를 할당한다. mmap_file을 생성 및 초기화하고 vm_entry를 생성 및 초기화한다. 성공 시 mapid를 반환한다.
munmap() 함수는 mmap_list를 순회하여 인자로 입력 받은 mapping id와 일치하는지 확인한다. 일치하는 vm_entry를 제거하고 페이지 테이블 엔트리를 제거한다. 마지막으로 mmap_file을 제거하고 file_close() 한다.
fd: 프로세스의 가상 주소공간에 맵핑할 파일
addr: 맵핑을 시작할 주소 (페이지 단위 정렬)
성공 시 mapping id를 리턴, 실패 시 에러코드(-1) 리턴
요구 페이징에 의해 파일 데이터를 메모리로 로드
mmap_list 내에서 mapping에 해당하는 mapid를 갖는 모든 vm_entry를 해제
인자로 넘겨진 mapping 값이 CLOSE_ALL인 경우 모든 파일 맵핑을 제거
페이지 테이블에서 엔트리 제거
맵핑 제거 시 do_munmap() 함수 호출
mmap_file의 vme_list에 연결된 모든 vm_entry들을 제거
페이지 테이블 엔트리 제거
vm_entry 가리키는 가상주소에 대한 물리 페이지가 존재하고, dirty하면 디스크에 메모리 내용을 기록
handle_mm_fault()를 통해 페이지 할당 여부를 확인 vm_entry 타입을 확인한다. VM_BI 파일일 경우 파일에서 메모리로 데이터를 로드하고 페이지 테이블을 셋업한다.
vm_entry 타입이 VM_FILE일 경우 데이터를 로드할 수 있도록 handle_mm_fault()를 수정한다.
프로세스가 종료될 시 mmap_list 내에서 mapping에 해당하는 mapid를 갖는 모든 vm_entry을 해제를 제거하도록 수정한다.