网站如何注册域名网站标题设计ps

系列文章目录
Linux 内核设计与实现
 深入理解 Linux 内核
 Linux 设备驱动程序
 Linux设备驱动开发详解
 深入理解Linux虚拟内存管理(一)
 深入理解Linux虚拟内存管理(二)
 深入理解Linux虚拟内存管理(三)
 深入理解Linux虚拟内存管理(四)
 深入理解Linux虚拟内存管理(五)
 深入理解Linux虚拟内存管理(六)
 深入理解Linux虚拟内存管理(七)
 深入理解Linux虚拟内存管理(八)
文章目录
- 系列文章目录
 - 一、进程内存描述符
 - 1、 进程内存描述符
 - (1)初始化一个描述符
 - (2)复制一个描述符
 - (a)copy_mm
 - (b)mm_init
 - ① ⇒ pgd_alloc
 - ② ⇒ kmem_cache_free
 
- (3)分配一个描述符
 - (a)allocate_mm
 - (b)mm_alloc
 
- (4)销毁一个描述符
 - (a)mmput
 - (b)mmdrop
 - (c)__mmdrop
 
- 2、创建内存区域
 - (1)创建一个内存区域
 - (a)do_mmap
 - (b)do_mmap_pgoff
 
- (2)插入一个内存区域
 - (a)__insert_vm_struct
 - (b)find_vma_prepare
 - (c)vma_link
 - (d)__vma_link
 - (e)__vma_link_list
 - (f)__vma_link_rb
 - (g)__vma_link_file
 
- (3)合并相邻区域
 - (a)vma_merge
 - (b)can_vma_merge
 
- (4)重映射并移动一个内存区域
 - (a)sys_mremap
 - (b)do_mremap
 - (c)move_vma
 - (d)make_pages_present
 - (e)get_user_pages
 - (f)move_page_tables
 - (g)move_one_page
 - (h)get_one_pte
 - (i)alloc_one_pte
 - (j)copy_one_pte
 
- (5)删除内存区域
 - (a)do_munmap
 - (b)unmap_fixup
 
- (6)删除所有的内存区域
 - (a)exit_mmap
 - (b)clear_page_tables
 - (c)free_one_pgd
 - (d)free_one_pmd
 
- 3、查找内存区域
 - (1)查找已映射内存区域
 - (a)find_vma
 - (b)find_vma_prev
 - (c)find_vma_intersection
 
- (2)查找空闲内存区域
 - (a)get_unmapped_area
 - (b)arch_get_unmapped_area
 
- 4、对内存区域上锁和解锁
 - (1)对内存区域上锁
 - (a)sys_mlock
 - (b)sys_mlockall
 - (c)do_mlockall
 - (d)do_mlock
 
- (2)对区域解锁
 - (a)sys_munlock
 - (b)sys_munlockall
 
- (3)上锁/解锁后修整区域
 - (a)mlock_fixup
 - (b)ulock_fixup_all
 - (c)mlock_fixup_start
 - (d)mlock_fixup_end
 - (e)mlock_fixup_middle
 
- 5、缺页中断
 - (1)x86 缺页中断处理程序
 - (a)do_page_fault
 
- (2)扩展栈
 - (a)expand_stack
 
- (3)独立体系结构的页面中断处理程序
 - (a)hanle_mm_fault
 - (b)handle_pte_fault
 
- (4)请求分配
 - (a)do_no_page
 - (b)do_anonymous_page
 
- (5)请求分页
 - (a)do_swap_page
 - (b)can_share_swap_page
 - (c)exclusive_swap_page
 
- (6)写时复制(COW) 页面
 - (a)do_wp_page
 
- 6、页面相关的磁盘 I/O
 - (1)一般文件读
 - (a)generic_file_read
 - (b)do_generic_file_read
 - (c)generic_file_readahead
 
- (2)一般文件 mmap
 - (a)generic_file_mmap
 
- (3)一般文件截断
 - (a)vmtruncate
 - (b)vmtruncate_list
 - (c)zap_page_range
 - (d)zap_pmd_range
 - (e)zap_pte_range
 - (f)truncate_inode_pages
 - (g)truncate_list_pages
 - (h)truncate_complete_page
 - (i)do_flushpage
 - (j)truncate_partial_page
 
- (4)从页面高速缓存中读入页面
 - (a)filemap_nopage
 - (b)age_cache_read
 
- (5)为 nopage() 进行预读文件
 - (a)nopage_sequential_readahead
 - (b)read_cluster_nonblocking
 
- (6)交换相关的预读
 - (a)swapin_readahead
 - (b)valid_swaphandles
 
- 符号
 
一、进程内存描述符
1、 进程内存描述符
(1)初始化一个描述符
传送门 4.3.2 初始化一个描述符
系统中的 mm_struct 开始称为 init_mm ,它在编译时由宏 INIT_MM() 静态初始化。
// include/linux/sched.h
#define INIT_MM(name) \
{			 				\mm_rb:		RB_ROOT,			\pgd:		swapper_pg_dir, 		\mm_users:	ATOMIC_INIT(2), 		\mm_count:	ATOMIC_INIT(1), 		\mmap_sem:	__RWSEM_INITIALIZER(name.mmap_sem), \page_table_lock: SPIN_LOCK_UNLOCKED, 		\mmlist:		LIST_HEAD_INIT(name.mmlist),	\
}// arch/i386/kernel/init_task.c
struct mm_struct init_mm = INIT_MM(init_mm);
 
新 mm_struct 在建立以后,是它们父 mm_struct 的备份,并且它们由 copy_mm() 以 init_mm() 初始化的字段来复制。
(2)复制一个描述符
(a)copy_mm
这个函数为给定的进程复制一份 mm_struct 。它仅在创建一个新进程后且需要它自己的 mm_struct 时由 do_fork() 调用。
// kernel/fork.c
// 这一块重置没有被子 mm_struct 继承的字段并找到一个复制源 mm 的字段。
// 这些参数是为克隆而传入的标志位和那些复制 mm_struct 的进程。
static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
{struct mm_struct * mm, *oldmm;int retval;// 初始化与内存管理相关的task_struct字段。tsk->min_flt = tsk->maj_flt = 0;tsk->cmin_flt = tsk->cmaj_flt = 0;tsk->nswap = tsk->cnswap = 0;tsk->mm = NULL;tsk->active_mm = NULL;/** Are we cloning a kernel thread?** We need to steal a active VM for that..*/// 借用当前运行进程的mm来复制。	 oldmm = current->mm;// 一个没有mm的内核线程,所以它可以立即返回。if (!oldmm)return 0;// 如果设置了 CLONE_VM 标志位,子进程将与父进程共享mm。像 pthreads 这// 样的用户需要这样做。mm_users 字段加1, 以使mm不会过早销毁。// good_mm 标记设置 tsk->mm 和 tsk->active_mm, 并返回成功if (clone_flags & CLONE_VM) {atomic_inc(&oldmm->mm_users);mm = oldmm;goto good_mm;}retval = -ENOMEM;// 分配新的mm。mm = allocate_mm();if (!mm)goto fail_nomem;/* Copy the current MM stuff.. */// 复制父mm, 并利用mm_init()来初始化特定进程的mm字段。memcpy(mm, oldmm, sizeof(*mm));if (!mm_init(mm))goto fail_nomem;// 为那些无法自动管理其MMU的体系结构初始化MMU上下文。if (init_new_context(tsk,mm))goto free_pt;// 调用dup_mmap(),它负责复制所有VMA父进程用到的区域。down_write(&oldmm->mmap_sem);retval = dup_mmap(mm);up_write(&oldmm->mmap_sem);// 一旦成功,dup_mmap() 返回 0。如果失败,标记 free_pt 将调用 mmput() 。它将// mm 的使用计数减 1if (retval)goto free_pt;/** child gets a private LDT (if there was an LDT in the parent)*/// 基于父进程为新进程复制LDT。 copy_segments(tsk, mm);good_mm:// 设置新mm,active_mm 并返回成功。tsk->mm = mm;tsk->active_mm = mm;return 0;free_pt:mmput(mm);
fail_nomem:return retval;
}
 
(b)mm_init
这个函数初始化特定进程的 mm 字段。
// kernel/fork.c
#define free_mm(mm)	(kmem_cache_free(mm_cachep, (mm)))static struct mm_struct * mm_init(struct mm_struct * mm)
{// 设置用户数为l。atomic_set(&mm->mm_users, 1);// 设置mm的引用计数为1。atomic_set(&mm->mm_count, 1);// 初始化保护VMA链表的信号量。init_rwsem(&mm->mmap_sem);// 初始化保护写访问的自旋锁。mm->page_table_lock = SPIN_LOCK_UNLOCKED;// 为该结构分配新的PGD。mm->pgd = pgd_alloc(mm);mm->def_flags = 0;if (mm->pgd)return mm;free_mm(mm);return NULL;
}
 
① ⇒ pgd_alloc
pgd_alloc 函数
② ⇒ kmem_cache_free
kmem_cache_free 函数
(3)分配一个描述符
提供了两个函数来分配一个 mm_struct。虽然有点容易混淆,但它们实际上都是一样的。allocate_mm() 将从 slab 分配器中分配一个 mm_struct 。 mm_alloc() 将分配结构,然后调用 mm_init() 来初始化。
(a)allocate_mm
// kernel/fork.c
#define allocate_mm()	(kmem_cache_alloc(mm_cachep, SLAB_KERNEL))
// 从slab分配器分配一个mm_struct。
 
(b)mm_alloc
// kernel/fork.c
/** Allocate and initialize an mm_struct.*/
struct mm_struct * mm_alloc(void)
{struct mm_struct * mm;// 从slab分配器分配一个mm_struct。mm = allocate_mm();if (mm) {// 将结构的所有字段归0。memset(mm, 0, sizeof(*mm));// 进行基本的初始化。		return mm_init(mm);}return NULL;
}
 
(4)销毁一个描述符
    mm 的一个新用户利用如下调用将使用计数加1:
     atomic_inc( &mm->mm_users );
     利用 mmput() 将使用计数减 1。如果 mm_users 计数减到 0,将调用 exit_mmap() 将所有的已映射区域删除,而且所有的页表也将会销毁,因为已经没有任何使用用户空间部分的使用者。mm_count 计数由 mmdrop() 减 1,因为页表和 VMA 的使用者都记为一个 mm_struct 使用者。在 mm_count 减到 0 时,mm_struct 将会被销毁。
(a)mmput
// kernel/fork.c
/** Decrement the use count and release all resources for an mm.*/
void mmput(struct mm_struct *mm)
{if (atomic_dec_and_lock(&mm->mm_users, &mmlist_lock)) {extern struct mm_struct *swap_mm;if (swap_mm == mm)swap_mm = list_entry(mm->mmlist.next, struct mm_struct, mmlist);list_del(&mm->mmlist);mmlist_nr--;spin_unlock(&mmlist_lock);exit_mmap(mm);mmdrop(mm);}
}
 
(b)mmdrop
(c)__mmdrop
2、创建内存区域
(1)创建一个内存区域
(a)do_mmap
(b)do_mmap_pgoff
(2)插入一个内存区域
(a)__insert_vm_struct
(b)find_vma_prepare
(c)vma_link
(d)__vma_link
(e)__vma_link_list
(f)__vma_link_rb
(g)__vma_link_file
(3)合并相邻区域
(a)vma_merge
(b)can_vma_merge
(4)重映射并移动一个内存区域
(a)sys_mremap
(b)do_mremap
(c)move_vma
(d)make_pages_present
(e)get_user_pages
(f)move_page_tables
(g)move_one_page
(h)get_one_pte
(i)alloc_one_pte
(j)copy_one_pte
(5)删除内存区域
(a)do_munmap
(b)unmap_fixup
(6)删除所有的内存区域
(a)exit_mmap
(b)clear_page_tables
(c)free_one_pgd
(d)free_one_pmd
3、查找内存区域
(1)查找已映射内存区域
(a)find_vma
(b)find_vma_prev
(c)find_vma_intersection
(2)查找空闲内存区域
(a)get_unmapped_area
(b)arch_get_unmapped_area
4、对内存区域上锁和解锁
(1)对内存区域上锁
(a)sys_mlock
(b)sys_mlockall
(c)do_mlockall
(d)do_mlock
(2)对区域解锁
(a)sys_munlock
(b)sys_munlockall
(3)上锁/解锁后修整区域
(a)mlock_fixup
(b)ulock_fixup_all
(c)mlock_fixup_start
(d)mlock_fixup_end
(e)mlock_fixup_middle
5、缺页中断
(1)x86 缺页中断处理程序
(a)do_page_fault
(2)扩展栈
(a)expand_stack
(3)独立体系结构的页面中断处理程序
(a)hanle_mm_fault
(b)handle_pte_fault
(4)请求分配
(a)do_no_page
(b)do_anonymous_page
(5)请求分页
(a)do_swap_page
(b)can_share_swap_page
(c)exclusive_swap_page
(6)写时复制(COW) 页面
(a)do_wp_page
6、页面相关的磁盘 I/O
(1)一般文件读
(a)generic_file_read
(b)do_generic_file_read
(c)generic_file_readahead
(2)一般文件 mmap
(a)generic_file_mmap
(3)一般文件截断
(a)vmtruncate
(b)vmtruncate_list
(c)zap_page_range
(d)zap_pmd_range
(e)zap_pte_range
(f)truncate_inode_pages
(g)truncate_list_pages
(h)truncate_complete_page
(i)do_flushpage
(j)truncate_partial_page
(4)从页面高速缓存中读入页面
(a)filemap_nopage
(b)age_cache_read
(5)为 nopage() 进行预读文件
(a)nopage_sequential_readahead
(b)read_cluster_nonblocking
(6)交换相关的预读
(a)swapin_readahead
(b)valid_swaphandles
符号
   
 ⇐ ⇒ ⇔ ⇆ ⇒ ⟺
 ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿
 ⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑿⒀⒁⒂⒃⒄⒅⒆⒇
 ➊➋➌➍➎➏➐➑➒➓⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴
 ⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵
 ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ
 ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ
 🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩
123
y = x 2 + z 3 y = x^2 + z_3 y=x2+z3
y = x 2 + z 3 + a b + b a y = x^2 + z_3 + \frac {a}{b} + \sqrt[a]{b} y=x2+z3+ba+ab
y = x 2 + z 3 (1) y = x^2 + z^3 \tag{1} y=x2+z3(1)
