lazy_load_segment에서 aux에 들어가는 구조체(segment_load_info)는 동적 할당받아 사용한다. 따라서 반드시 해제해주어야한다. 문제는 해제가 여러군데에서 일어나야 한다는 점이다.
struct segment_load_info {
struct file *file; // 불러올 파일
off_t offset; // 읽기 시작할 부분
size_t read_bytes; // 읽을 크기
size_t zero_bytes; // 0으로 채울 크기
};
aux 구조체(segment_load_info) 는 load_segment 에서 생성된다. 그리고 생성에 실패하면, 즉시 해제한다.
/* 프레임 초기화를 위한 정보 */
struct load_info aux = malloc(sizeof(*aux));
aux.file = file;
aux.offset = offset;
size_t read_bytes = read_bytes;
size_t zero_bytes = zero_bytes;
/* 사용자 가상 페이지를 lazy loading 대상으로 등록. */
if (!vm_alloc_page_with_initializer (VM_ANON, upage,
writable, lazy_load_segment, aux)) {
/* aux 구조체 해제*/
free(aux);
return false;
}
생성에 성공했다면, 해제되는 시점은 아래와 같아.
page fault가 일어나면, lazy_load_segment에서 프레임에 데이터를 적재한다. 즉, 더이상 aux 구조체가 필요없어진다. 따라서 lazy_load_segemnt에서 정리해주어야한다.
static bool
lazy_load_segment(struct page *page, void *aux)
{
/* page와 aux를 이용해 데이터를 프레임으로 올리는 함수 */
struct segment_load_info* info = aux;
bool success = false;
/* 프레임에 파일 내용 로드 */
if (file_read(info->file, page->frame->kva, info->read_bytes) != info->read_bytes)
{
goto done;
}
/* 남는 공간은 0으로 초기화 */
memset((uint8_t *)page->frame->kva + info->read_bytes, 0, info->zero_bytes);
success = true;
done:
/* 결과와 상관없이 aux 구조체를 해제 */
free(info);
return success;
}
lazy_load_segment에서 정리해야하는걸 알아내는데 힌트가 있다. load_segment에서 lazy_load_segment는 aux를 사용하는 callback 함수로 넘겨진다. 따라서, aux를 사용하는것은 load_segment임을 알 수 있다.
if (!vm_alloc_page_with_initializer (VM_ANON, upage,
writable, lazy_load_segment, aux))
...