2016-12-09 6 views
0

페이지 테이블 엔트리가 이미 존재하더라도 의도적으로 페이지 폴트를 발생시키고 싶습니다.페이지 폴트를 올리는 방법

그래서 _PAGE_PRESENT 비트를 지워 페이지 오류를 생성했습니다.

pte = get_locked_pte(mm, addr, &ptl); 
entry = *pte; 
entry = pte_clear_flags(entry, _PAGE_PRESENT); 
set_pte_at(mm, addr, pte, entry); 
pte_unmap_unlock(pte, ptl); 
flush_tlb_range(vma, vma->vm_start, vma->vm_end); 

그러나,이 코드가 작동하지 않습니다

여기에 내가 쓴 커널 코드입니다. 의도 한 페이지 오류가 발생하지 않습니다. 정확히 어떻게 페이지 오류를 일으킬 수 있는지 알고 싶습니다.

감사합니다.

+0

커널 코드 또는 사용자 영역 코드를 작성 하시겠습니까? –

+1

사용자 코드로 페이지 오류를 트립 할 커널 코드를 작성하고 있습니까? – jxh

+0

위의 코드는 커널 코드입니다. 위의 코드에서 "addr"은 사용자 공간의 주소입니다. –

답변

0

@Jungsik Choi, 현재 페이지에 대해 NOT PRESENT 플래그를 설정하면 페이지 테이블 항목이 손상됩니다. 실제로 플래그를 NOT PRESENT로 변경하면 플래그가 변경되지만 아무것도 표시되지 않습니다. 따라서 귀하의 페이지는 여전히 사실입니다. 이 방법으로 NOT PRESENT 플래그를 설정하면 PTE가 손상되고 페이지 오류가 발생하지 않습니다.

페이지 폴트를 관찰하려면 디스크에서 강제로 읽어야합니다. 다음의 코드는 커맨드 라인에서 주어진 파일을 매핑하여 필요하지 않은 커널에게 알립니다. 파일 (은/usr/bin에 큰 파일을 선택) 충분히 큰 경우, 당신은 항상 주요 페이지 오류를 얻을 것이다 : 오류 처리의 방법으로 많이 없다

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

int main(int argc, char ** argv) { 
    int fd = open(argv[1], O_RDONLY); 
    struct stat stats; 
    fstat(fd, &stats); 
    posix_fadvise(fd, 0, stats.st_size, POSIX_FADV_DONTNEED); 
    char * map = (char *) mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0); 
    if (map == MAP_FAILED) { 
    perror("Failed to mmap"); 
    return 1; 
    } 
    int result = 0; 
    int i; 
    for (i = 0; i < stats.st_size; i++) { 
    result += map[i]; 
    } 
    munmap(map, stats.st_size); 
    return result; 
} 

, 이것은 단지이다 아이디어를 입증하십시오. 내 시스템에서

gcc majorfault.c -o majorfault && /usr/bin/time -v ./majorfault /usr/bin/git-annex 

은 항상 154 개의 주요 페이지 오류를 생성합니다.