페이지는 일반적인 파일시스템의 파일이나 블록 디바이스 파일, 메모리맵 파일로부터 생성된다. 이러한 식으로 페이지 캐시는 최근에 파일을 접근하면서 얻은 모든 페이지를 저장하게 된다. 페이지 IO연산, 예를 들면 read()를 호출하기 전에, 커널은 해당 데이터가 페이지 캐시 안에 있는가를 검사하게 된다. 만약 찾는 데이터가 페이지 캐시 안에 있다면 커널은 디스크에서 해당 데이터를 읽어오기보다는 즉시 그 페이지를 돌려줄 수 있게 된다.
address_space객체
- 페이지는 비연속적인 다수의 물리적 블록으로 구성될 수 있다. 이러한 페이지에서 찾는 데이터가 포함 돼 있는가를 검사하는 것은 어려운데, 그것은 페이지를 구성하는 블록의 비연속성 때문이다.
즉, 비 연속성으로 인하여 디바이스 이름과 블록 번호만을 가지고는 어떤 데이터으 ㅣ페이지 캐시에서의 위치를 더욱이 알아낼 수가 없다.
범용성을 유지하기 위해, 리눅스의 페이지 캐시는 캐시 안의 페이지를 구별하기 위해 address_space구조체를 사용한다.
이 구조체는 <linux/fs.h>에 정의되어있다.
i_mmap 필드는 해당 주소 공간의 모든 공유/비공유 매핑들에 대한 우선순위 탐색트리이다.
우선순위 탐색 트리는 힙과 래딕스(radix tree)를 멋지게 섞어놓은 것이다.
address_space는 어떤 커널 객체, 일반적으로는 inode와 연관된다. 만약 inode라면, host필드는 그 inode를 가리킨다. 반면 inode가 아닐 경우, 예를들어 address_space가 swapper와 연관된 경우에는 host 필드가 NULL이다.
a_ops필드는 주소공간에 대한 연산 테이블을 가리킨다. 연산 테이블은 struct address_space_operations 구조체로 표현되며, 이것 또한 <linux/fs.h>에 정의돼있다.
readpage(), writepage()가 가장중요하다.
address_space객체
- 페이지는 비연속적인 다수의 물리적 블록으로 구성될 수 있다. 이러한 페이지에서 찾는 데이터가 포함 돼 있는가를 검사하는 것은 어려운데, 그것은 페이지를 구성하는 블록의 비연속성 때문이다.
즉, 비 연속성으로 인하여 디바이스 이름과 블록 번호만을 가지고는 어떤 데이터으 ㅣ페이지 캐시에서의 위치를 더욱이 알아낼 수가 없다.
범용성을 유지하기 위해, 리눅스의 페이지 캐시는 캐시 안의 페이지를 구별하기 위해 address_space구조체를 사용한다.
이 구조체는 <linux/fs.h>에 정의되어있다.
635struct address_space { 636 struct inode *host; /* 해당페이지를 소유한 inode */ 637 struct radix_tree_root page_tree; /* 모든 페이지들에 대한 radix tree */ 638 spinlock_t tree_lock; /* page_tree에 대한 락 */ 639 unsigned int i_mmap_writable;/* VM_SHARED 매핑 카운트 */ 640 struct prio_tree_root i_mmap; /* 모든 매핑들의 리스트 */ 641 struct list_head i_mmap_nonlinear;/*VM_NONLINEAR 매핑 리스트 */
642 struct mutex i_mmap_mutex; /* i_mmap 항목에 대한 락*/ 643 /* Protected by tree_lock together with the radix tree */ 644 unsigned long nrpages; /* 페이지의 총수 */ 645 pgoff_t writeback_index;/* 라이트백 시작 오프셋 */ 646 const struct address_space_operations *a_ops; /* 연산테이블 */ 647 unsigned long flags; /* error bits/gfp mask */ 648 struct backing_dev_info *backing_dev_info; /* device readahead, etc */ 649 spinlock_t private_lock; /* for use by the address_space */ 650 struct list_head private_list; /* ditto */ 651 struct address_space *assoc_mapping; /* ditto */ 652} __attribute__((aligned(sizeof(long))));
i_mmap 필드는 해당 주소 공간의 모든 공유/비공유 매핑들에 대한 우선순위 탐색트리이다.
우선순위 탐색 트리는 힙과 래딕스(radix tree)를 멋지게 섞어놓은 것이다.
address_space는 어떤 커널 객체, 일반적으로는 inode와 연관된다. 만약 inode라면, host필드는 그 inode를 가리킨다. 반면 inode가 아닐 경우, 예를들어 address_space가 swapper와 연관된 경우에는 host 필드가 NULL이다.
a_ops필드는 주소공간에 대한 연산 테이블을 가리킨다. 연산 테이블은 struct address_space_operations 구조체로 표현되며, 이것 또한 <linux/fs.h>에 정의돼있다.
582struct address_space_operations { 583 int (*writepage)(struct page *page, struct writeback_control *wbc); 584 int (*readpage)(struct file *, struct page *); 585 586 /* Write back some dirty pages from this mapping. */ 587 int (*writepages)(struct address_space *, struct writeback_control *); 588 589 /* Set a page dirty. Return true if this dirtied it */ 590 int (*set_page_dirty)(struct page *page); 591 592 int (*readpages)(struct file *filp, struct address_space *mapping, 593 struct list_head *pages, unsigned nr_pages); 594 595 int (*write_begin)(struct file *, struct address_space *mapping, 596 loff_t pos, unsigned len, unsigned flags, 597 struct page **pagep, void **fsdata); 598 int (*write_end)(struct file *, struct address_space *mapping, 599 loff_t pos, unsigned len, unsigned copied, 600 struct page *page, void *fsdata); 601 602 /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ 603 sector_t (*bmap)(struct address_space *, sector_t); 604 void (*invalidatepage) (struct page *, unsigned long); 605 int (*releasepage) (struct page *, gfp_t); 606 void (*freepage)(struct page *); 607 ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov, 608 loff_t offset, unsigned long nr_segs); 609 int (*get_xip_mem)(struct address_space *, pgoff_t, int, 610 void **, unsigned long *); 611 /* migrate the contents of a page to the specified target */ 612 int (*migratepage) (struct address_space *, 613 struct page *, struct page *); 614 int (*launder_page) (struct page *); 615 int (*is_partially_uptodate) (struct page *, read_descriptor_t *, 616 unsigned long); 617 int (*error_remove_page)(struct address_space *, struct page *); 618};
readpage(), writepage()가 가장중요하다.