달력

6

« 2025/6 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2011. 11. 1. 00:17

페이지 캐시 OS이야기2011. 11. 1. 00:17

페이지는 일반적인 파일시스템의 파일이나 블록 디바이스 파일, 메모리맵 파일로부터 생성된다. 이러한 식으로 페이지 캐시는 최근에 파일을 접근하면서 얻은 모든 페이지를 저장하게 된다. 페이지 IO연산, 예를 들면 read()를 호출하기 전에, 커널은 해당 데이터가 페이지 캐시 안에 있는가를 검사하게 된다. 만약 찾는 데이터가 페이지 캐시 안에 있다면 커널은 디스크에서 해당 데이터를 읽어오기보다는 즉시 그 페이지를 돌려줄 수 있게 된다.

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()가 가장중요하다.









 

'OS이야기' 카테고리의 다른 글

버퍼 캐시  (0) 2011.11.01
래딕스 트리  (0) 2011.11.01
fread() / fwrite()  (0) 2011.10.31
메모리영역 다루기  (0) 2011.10.31
VMA연산  (0) 2011.10.25
:
Posted by НooпeУ


Code Start Code End