페이지 캐시의 물리 어드레스 알아내기
이전 질문을 올렸었는데 아무도 답변을 달아 주시지 않으셔서 알아낸 점을들 첨부하여 다시 질문을 올립니다.
페이지 캐시의 물리 어드레스를 알아내고자 하고 있습니다만, 커널이 어떻게 페이지캐시에 접근 하는지에 대해서는 알지 못하고 있는 상태 입니다.
우선 가장 먼저, 존재하는 커널 소스를 분석하는 것이 가장 편하리라 생각하고, 페이지 캐시를 디스크에 동기화 시키는 시스템콜인 sys_sync시스템콜의 동작 과정을 확인하려 하였습니다.(이 녀석은 분명히 페이지 캐시의 위치만을 알고 있을 것 입니다.)
http://lxr.linux.no/linux+v3.0.4/fs/sync.c#L99
이것이 시스템 콜의 바디 입니다.
이 곳에서 알아낸 점은, 제일 위에서 불러내는 flusher커널 스레드가 페이지 캐시를 탐색하는 작업을 하여, 쓰기작업 큐에 큐잉 시킨다는 점 을 알아 냈습니다.
밑의 sync_filesystem(0)/(1)이 아마도 디스크에 직접 쓰기 작업(writeback)을 하는 부분이라고 추측 됩니다.
flusher의 소스를 분석하여, 직접적인 동작 과정을 알아내 보려 하였으나, 아직 실력이 부족해서인지, 정확한 동작 과정을 알아내진 못하였습니다.
라이트백 작업은 물리메모리의 데이터를 디스크상에 적어넣는 부분이 존재하기 때문에(더티 페이지만으로 한정 되긴 하지만요) 분명히 메모리의 물리 어드레스를 알 수 있으리라 추측하고 소스를 분석 해 보았습니다.
do_writepages()
http://lxr.linux.no/linux+v3.0.4/mm/page-writeback.c#L1058
mpage_writepages()
http://lxr.linux.no/linux+v3.0.4/fs/mpage.c#L677
을 거쳐 최종적으로
write_cache_pages()
http://lxr.linux.no/linux+v3.0.4/mm/page-writeback.c#L863
가 호출 되는 것을 확인 하였습니다.
이곳에서 pgoff_t index와 pgoff_t end가 아마도 메모리상의 물리 어드레스를 저장하는 녀석이 되리라고 추측 하였습니다.(근거 : http://lxr.linux.no/linux+v3.0.4/include/linux/writeback.h#L27 의 주석)
그래서 printk 를 사용하여 882-883 의 사이와 888-889 사이에서(여기선 wbc->range_start/end로 접근) 커널 메시지를 출력 시켜 보았습니다.
(애당초 range_cyclic 이 뭔지 모르겠습니다만,) 사이클릭일 경우 커널공간으로 추측 되는 상위 어드레스가 1개 출력 됩니다만, 이외의 경우 start/end 두개의 어드레스가 제대로 출력 되지 않습니다.(%p로 출력 할 경우 start 가 (NULL)로 나오며, end 는 물리 어드레스로 추정되는 어드레스가 출력 됩니다.)
현재까지 이정도의 진행밖에 못한 상황 입니다만, 만에 하나 지금 출력한 물리 어드래스가 맞는 주소라고 쳐도, 결과적으론 이는 페이지캐시의 물리 어드래스가 아닌, 페이지 캐시의 극히 일부인 더티비트의 어드래스만 출력하는 꼴이 되어 버립니다.
커널은 분명 자신의 페이지테이블을 소유하고 있을 것이고, 그를 참조하면 쉽게 메모리 관리 정책에 관한 어드레스도 얻어 올 수 있을 듯 한데, 이 부분에 대한 공부가 부족하여 현재로선 이 방법이 유일한 접근 방법이라고 생각 하고 있습니다.
위에서 출력 시킨 start/end 의 어드래스중 하나가 Null 인 이유와, 페이지 캐시의 물리 어드레스를 알아내기 위한 좋은 방법에 대한 조언을 부탁 드리겠습니다.
감사합니다.
내용추가
조금 다른 방법을 사용하여 더티비트의 주소를 출력 하는 데는 성공 하였습니다.
http://lxr.linux.no/linux+v3.0.4/mm/page-writeback.c#L965
이 곳의 1행 앞에
printk("Write to : 0x%p\n",virt_to_phys(page_address(page)));//my second mod. Physical address of writtened dirty bit
를 적어 넣었습니다.
직접 쓰기 작업이 일어나기 직전의 페이지 디스크립터 로부터 가상 어드레스를 얻은 후, 그것을 물리 어드레스로 변환하는 방법을 사용 하였습니다.
이를 통해 더티비트의 어드레스는 알아 냈으나, 페이지 캐시가 사용중인 모든 어드래스를 알아내지는 못하였습니다.
다른 방법을 찾아보고 있습니다.
고수님들의 지적 부탁드립니다^^.
좀 딴얘기
도움이 안되는 얘기라 죄송합니다만... 노파심에...
"페이지 캐시의 물리주소"를 알아내려고 하는 게 커널 안에서 그 주소를 이용해 뭐를 해보려고 한다거나 (DMA?) 아니면 그냥 커널 소스를 공부해보는 목적이라면 별로 상관없습니다만, 그 주소를 시스템콜로 유저 프로세스에 돌려줘서 뭔가에 써먹는 거라면 문제가 생길 수 있습니다.
왜냐하면 유저 프로세스에서 그 주소를 받을 때에는 이미 그 주소가 유효하다는 보장이 없거든요. 그 사이에 preemption이 일어나 주소가 딴데로 바뀌었을 수 있죠.
목적
마이그레이션시의 부하를 줄여보기 위한 시도중 한가지 입니다^^.
목적
마이그레이션시의 부하를 줄여보기 위한 시도중 한가지 입니다^^.
linux page cache 관련해서 검색하다가 이
linux page cache 관련해서 검색하다가 이 게시물을 보았네요
현재 제가 공부한 지식내에서 내용을 알려드리면
page cache 내에 있는 각 page 의 물리 주소를 알고 싶으신 것인거죠?
- page cache 는 struct address_space 구조체로 관리됩니다.
- 보통 inode에 들어 있는데요, i_mapping 변수 입니다.
- struct address_space 구조체의 page_tree 를 따라가시면 현재 page cache 에서 캐쉬하고 있는 각 page 를 알수 있습니다. (따라가는 부분은 linux 소스 코드를 확인해 보세요)
- 즉, struct page 구조체 정보를 알수 있는데요, struct page 구조체 정보에서 실제 물리주소 정보를 알아내실수 있을듯 합니다.
댓글 달기