【正文】
page = lookup_swap_cache(entry)查看交換槽對應的頁面是否存在于交換緩存中,如果是則跳到第6步;3)調(diào)用swapin_readahead(entry, address, vma)從交換區(qū)中讀取一組頁面,對每個頁面調(diào)用read_swap_cache_async()讀取該頁面;4)對于進程訪問異常的頁面再次調(diào)用read_swap_cache_async()。因為swapin_readahead調(diào)用可能失敗,在它成功的情況下read_swap_cache_async()發(fā)現(xiàn)該頁面在交換緩存里,很快返回;5)如果頁面還是沒有在交換緩存中,可能存在其他內(nèi)核控制路徑已經(jīng)把該頁面換入。比較page_table對應的pte內(nèi)容與orig_pte是否相同,如果不同,說明頁面已經(jīng)換入。函數(shù)跳出返回。6)如果頁面在交換緩存中,調(diào)用mark_page_accessed并鎖住該頁面;7)pte_offset_map_lock(mm, pmd, address, amp。ptl)獲取page_table對應的pte內(nèi)容,與orig_pte比較,判斷是否有其他內(nèi)核控制路徑進行換入操作;8)測試PG_uptodate標志,如果未設置,則出錯返回;9)增加mmanon_rss的計數(shù);10)mk_pte(page, vmavm_page_prot)創(chuàng)建PTE并設置標志,插入到進程頁表中;11)page_add_anon_rmap()為該匿名頁插入反向映射數(shù)據(jù)結構的內(nèi)容;12)swap_free(entry)釋放頁槽;13)檢查交換緩存負載是否達到50%,如果是,并且該頁面僅被觸發(fā)頁面訪問異常的進程占有,則從交換緩存中釋放該頁。14)如果write_access標志為1,說明是COW寫時復制,調(diào)用do_wp_page()拷貝一份該頁面;15)釋放頁鎖和頁面緩存等,并返回結果。附錄1:進程空間數(shù)據(jù)結構struct mm_struct {struct vm_area_struct * mmap。/* list of VMAs */struct rb_root mm_rb。struct vm_area_struct * mmap_cache。/* last find_vma result */unsigned long (*get_unmapped_area) (struct file *filp,unsigned long addr, unsigned long len,unsigned long pgoff, unsigned long flags)。void (*unmap_area) (struct mm_struct *mm, unsigned long addr)。unsigned long mmap_base。/* base of mmap area */unsigned long task_size。/* size of task vm space */unsigned long cached_hole_size。/* if nonzero, the largest hole below free_area_cache */unsigned long free_area_cache。/* first hole of size cached_hole_size or larger */pgd_t * pgd。atomic_t mm_users。/* How many users with user space? */atomic_t mm_count。/* How many references to struct mm_struct (users count as 1) */int map_count。/* number of VMAs */struct rw_semaphore mmap_sem。spinlock_t page_table_lock。/* Protects page tables and some counters */struct list_head mmlist。/* List of maybe swapped mm39。s.These are globally strung* together off , and are protected* by mmlist_lock*//* Special counters, in some configurations protected by the* page_table_lock, in other configurations by being atomic.*/mm_counter_t _file_rss。mm_counter_t _anon_rss。unsigned long hiwater_rss。/* Highwatermark of RSS usage */unsigned long hiwater_vm。/* Highwater virtual memory usage */unsigned long total_vm, locked_vm, shared_vm, exec_vm。unsigned long stack_vm, reserved_vm, def_flags, nr_ptes。unsigned long start_code, end_code, start_data, end_data。unsigned long start_brk, brk, start_stack。unsigned long arg_start, arg_end, env_start, env_end。unsigned long saved_auxv[AT_VECTOR_SIZE]。 /* for /proc/PID/auxv */cpumask_t cpu_vm_mask。/* Architecturespecific MM context */mm_context_t context。/* Swap token stuff *//** Last value of global fault stamp as seen by this process.* In other words, this value gives an indication of how long* it has been since this task got the token.* Look at mm/*/unsigned int faultstamp。unsigned int token_priority。unsigned int last_interval。unsigned char dumpable:2。/* coredumping support */int core_waiters。struct pletion *core_startup_done, core_done。/* aio bits */rwlock_tioctx_list_lock。struct kioctx*ioctx_list。}。/** Linux kernel virtual memory manager primitives.* The idea being to have a virtual mm in the same way* we have a virtual fs giving a cleaner interface to the* mm details, and allowing different kinds of memory mappings* (from shared memory to executable loading to arbitrary* mmap() functions).*//** This struct defines a memory VMM memory area. There is one of these* per VMarea/task.A VM area is any part of the process virtual memory* space that has a special rule for the pagefault handlers (ie a shared* library, the executable area etc).*/struct vm_area_struct {struct mm_struct * vm_mm。/* The address space we belong to. */unsigned long vm_start。/* Our start address within vm_mm. */unsigned long vm_end。/* The first byte after our end addresswithin vm_mm. *//* linked list of VM areas per task, sorted by address */struct vm_area_struct *vm_next。pgprot_t vm_page_prot。/* Access permissions of this VMA.該VMA中每個PTE的保護標志位和屬性標志位*/unsigned long vm_flags。/* Flags, listed below. */struct rb_node vm_r