"Conception et mise en œuvre du noyau Linux" Lecture du cache de pages de notes et de la réécriture de pages

Cache de page

Le cache de page est un cache disque implémenté par le noyau Linux, et sa fonction principale est de réduire les opérations d'E / S sur le disque.

Le cache de pages est composé de pages physiques en mémoire et son contenu correspond à des blocs physiques sur le disque.

Lorsque le noyau démarre une opération de lecture, il vérifie d'abord si les données requises se trouvent dans le cache de pages.

Il existe plusieurs stratégies pour la mise en cache d'écriture:

  • Ne pas mettre en cache
  • Mettre à jour le cache mémoire et les fichiers disque en même temps;
  • Réécriture: les données sont écrites directement dans le cache mémoire et l'écriture sur le disque est traitée plus tard dans le processus de réécriture (complété par le thread flusher, et peut être complété par les appels système sync () et fsync () dans le processus utilisateur);

Le cache de page peut être ajusté dynamiquement.

Lorsqu'il a besoin de faire de la place pour d'autres endroits, il adoptera une stratégie de récupération du cache pour récupérer le cache mémoire.

Linux adopte une stratégie à double chaîne.

Le cache de page met en cache tous les objets basés sur des pages, y compris divers types de fichiers et divers types de mappage de mémoire. (Comme mentionné précédemment, c'est principalement pour la mise en cache de disque, mais il y en a en fait beaucoup qui peuvent être mis en cache)

 

objet address_space

Le cache de page Linux utilise la structure adresse_space pour gérer les entrées de cache et les opérations d'E / S de page.

La structure adresse_space est la suivante:

struct address_space {
    struct inode        *host;      /* owner: inode, block_device */
    struct radix_tree_root  page_tree;  /* radix tree of all pages */
    spinlock_t      tree_lock;  /* and lock protecting it */
    unsigned int        i_mmap_writable;/* count VM_SHARED mappings */
    struct prio_tree_root   i_mmap;     /* tree of private and shared mappings */
    struct list_head    i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
    spinlock_t      i_mmap_lock;    /* protect tree, count, list */
    unsigned int        truncate_count; /* Cover race condition with truncate */
    unsigned long       nrpages;    /* number of total pages */
    pgoff_t         writeback_index;/* writeback starts here */
    const struct address_space_operations *a_ops;   /* methods */
    unsigned long       flags;      /* error bits/gfp mask */
    struct backing_dev_info *backing_dev_info; /* device readahead, etc */
    spinlock_t      private_lock;   /* for use by the address_space */
    struct list_head    private_list;   /* ditto */
    struct address_space    *assoc_mapping; /* ditto */
} __attribute__((aligned(sizeof(long))));

Parmi eux, a_ops pointe vers la table des fonctions d'opération dans l'objet d'espace d'adressage:

struct address_space_operations {
    int (*writepage)(struct page *page, struct writeback_control *wbc);
    int (*readpage)(struct file *, struct page *);
    void (*sync_page)(struct page *);
    /* Write back some dirty pages from this mapping. */
    int (*writepages)(struct address_space *, struct writeback_control *);
    /* Set a page dirty.  Return true if this dirtied it */
    int (*set_page_dirty)(struct page *page);
    int (*readpages)(struct file *filp, struct address_space *mapping,
            struct list_head *pages, unsigned nr_pages);
    int (*write_begin)(struct file *, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned flags,
                struct page **pagep, void **fsdata);
    int (*write_end)(struct file *, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned copied,
                struct page *page, void *fsdata);
    /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
    sector_t (*bmap)(struct address_space *, sector_t);
    void (*invalidatepage) (struct page *, unsigned long);
    int (*releasepage) (struct page *, gfp_t);
    ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
            loff_t offset, unsigned long nr_segs);
    int (*get_xip_mem)(struct address_space *, pgoff_t, int,
                        void **, unsigned long *);
    /* migrate the contents of a page to the specified target */
    int (*migratepage) (struct address_space *,
            struct page *, struct page *);
    int (*launder_page) (struct page *);
    int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
                    unsigned long);
    int (*error_remove_page)(struct address_space *, struct page *);
};

 

Je suppose que tu aimes

Origine blog.csdn.net/jiangwei0512/article/details/106153195
conseillé
Classement