struct page介绍

struct page

struct page {
	unsigned long flags;		

	union {
		struct {	                           /* Page cache and anonymous pages */

			struct list_head lru;

			struct address_space *mapping;
			pgoff_t index;		               /* Our offset within mapping. */

			unsigned long private;
		};
		struct {	                           /* slab, slob and slub */
			union {
				struct list_head slab_list;	   /* uses lru */
				struct {	                   /* Partial pages */
					struct page *next;
					int pages;	               /* Nr of pages left */
					int pobjects;	           /* Approximate count */

				};
			};
			struct kmem_cache *slab_cache;     /* not slob */
			void *freelist;		               /* first free object */
			union {
				void *s_mem;	               /* slab: first object */
				unsigned long counters;		   /* SLUB */
				struct {			           /* SLUB */
					unsigned inuse:16;
					unsigned objects:15;
					unsigned frozen:1;
				};
			};
		};
		struct {	                           /* Tail pages of compound page */
			unsigned long compound_head;	   /* Bit zero is set */

			                                   /* First tail page only */
			unsigned char compound_dtor;
			unsigned char compound_order;
			atomic_t compound_mapcount;
		};
		struct {	                           /* Second tail page of compound page */
			unsigned long _compound_pad_1;	   /* compound_head */
			unsigned long _compound_pad_2;
			struct list_head deferred_list;
		};
		struct {	                           /* Page table pages */
			unsigned long _pt_pad_1;	       /* compound_head */
			pgtable_t pmd_huge_pte;            /* protected by page->ptl */
			unsigned long _pt_pad_2;	       /* mapping */
			union {
				struct mm_struct *pt_mm;       /* x86 pgds only */
				atomic_t pt_frag_refcount;     /* powerpc */
			};

			spinlock_t *ptl;

		};
		struct {	                           /* ZONE_DEVICE pages */
			                                   /** @pgmap: Points to the hosting device page map. */
			struct dev_pagemap *pgmap;
			unsigned long hmm_data;
			unsigned long _zd_pad_1;	       /* uses mapping */
		};		                                     
		struct rcu_head rcu_head;              /** @rcu_head: You can use this to free a page by RCU. */
	};

	union {		                               /* This union is 4 bytes in size. */
		atomic_t _mapcount;

		unsigned int page_type;

		unsigned int active;		           /* SLAB */
		int units;		     	               /* SLOB */
	};

	atomic_t _refcount;
	struct mem_cgroup *mem_cgroup;
	void *virtual;			                   /* Kernel virtual address (NULL if not kmapped, ie. highmem) */
	int _last_cpupid;
} _struct_page_alignment;

page flags标志

enum pageflags {
    PG_locked,        // 表示页面已经上锁了。如果该比特位置位,说明页面已经被锁定;内存管理其他模块不能访问这个页面,以防发生竞争。
    PG_referenced,    // 表示页面刚被访问过,控制页面活跃程度,在kswapd页面回收中使用。
    PG_uptodate,      // 表示page的数据已经与后备存储器是同步的。即页的数据已经从块设备读取,且没有出错,数据是最新的。
    PG_dirty,         // 表示页面内容发生改变,页面为脏,页面内容被改写后还没有和外部存储器进行同步操作。
    PG_lru,           // 表示页面加入了LRU链表,内核使用LRU链表管理活跃和不活跃页面。
    PG_active,        // 表示page处于inactive LRU链表,控制页面活跃程度,在kswapd页面回收中使用。
	PG_workingset,
	PG_waiters,       // 页面有等待者,请检查其等待队列。本标志必须是bit7,并且与“ PG_locked”在同一字节中。
    PG_error,         // 页面操作过程中发生错误会设置该位。	
    PG_slab,          // 用于slab分配器
    PG_owner_priv_1,  // 页面的所有者使用,如果是page cache页面,文件系统可能使用。
    PG_arch_1,        // 特定体系结构的页面状态位。一般的代码保证当页面首次进入页面缓存时,该位将被清除。
    PG_reserved,      // 表示该页不可被换出。
    PG_private,       // 表示该页是有效的,如果页面是page cache,那么包含一些文件系统相关的数据信息。
    PG_private_2,     // 如果是page cache,可能包含fs aux data。
    PG_writeback,     // 表示页面的内容正在向块设备进行回写。
    PG_head,          /* A head page */
    PG_mappedtodisk,  // Has blocks allocated on-disk
    PG_reclaim,       // 表示该页马上要被回收。
    PG_swapbacked,    // 表示该page的后备存储器是swap,通常匿名页面才可以写回swap分区。
    PG_unevictable,   // 表示页面不可回收。
    PG_mlocked,       // 表示页面对应的VMA处于locked状态。
	PG_plink,         /*  page linked to a process */
    PG_uncached,      // Page has been mapped as uncached
    PG_hwpoison,      //  hardware poisoned page. Don't touch
	PG_young,
	PG_idle,
	PG_vital,
	PG_staple,
	PG_candi,

    __NR_PAGEFLAGS,
    
    PG_checked = PG_owner_priv_1,     /* Filesystems */
    PG_swapcache,                     // 表示页面处于交换缓存

    PG_fscache    = PG_private_2,     /* page backed by cache */
    PG_pinned     = PG_owner_priv_1,  /* Pinned in Xen as a read-only pagetable page. */    
    PG_savepinned = PG_dirty,         /* Pinned as part of domain save (see xen_mm_pin_all()). */    
    PG_foreign    = PG_owner_priv_1,  /* Has a grant mapping of another (foreign) domain's page. */
    PG_slob_free  = PG_private,       /* SLOB */
	PG_double_map = PG_private_2,     /* Compound pages. Stored in first tail page's flags */
	PG_isolated   = PG_reclaim,	      /* non-lru isolated movable page */
}

struct page数据结构成员flags定义了一个标志位PG_locked,内核利用PG_locked来设置一个页面锁。lock_page()函数用于申请页面锁,如果页面锁被其他进程占用了,那么会睡眠等待。

1)__lock_page(struct page *__page)
   用于申请页面锁,若page被其他进程使用,则需要睡眠等待

2)trylock_page(struct page *page)
   用于尝试申请页面锁,若page被其他进程使用,则直接返回false

test_and_set_bit函数详解:

test_and_set_bit(unsigned int nr, volatile unsigned long *p)
功能:设置指针p的第nr bit为1,然后返回指针p原来的nr bit的值

-->1)unsigned long mask = BIT_MASK(nr)
      mask的nr bit值为1
	  
-->2)p += BIT_WORD(nr)
      一般BIT_WORD(nr)为0

-->3)if (READ_ONCE(*p) & mask) return 1;
      判断指针p的第nr bit若为1,则直接返回1
	  
-->4)old = atomic_long_fetch_or(mask, (atomic_long_t *)p)
      给指针p与mask进行or运算,并返回指针p原来的nr bit值

-->5)return !!(old & mask)
      返回指针p原来nr bit位的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值