一、地址空间

进程地址空间由进程可寻址的虚拟内存组成,内核允许进程使用这种虚拟内存中的地址。

每个进程都有一个32位或64位的平坦地址空间,空间的具体大小取决于体系结构。“平坦”指的是地址空间范围是一个独立的连续区间。

现代采用虚拟内存的操作系统通常都使用平坦地址空间而不是分段式的内存模式。

一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上也彼此互不相干。这样的进程为线程。

一个进程可以寻址4GB虚拟内存(32位地址空间中),但这不代表能访问所有虚拟地址。可以被合法访问的地址空间称为内存区域。

进程只能访问有效内存区域内的内存地址,每个内存区域也具有相关权限如对相关进程有可读、可写、可执行属性。

如果一个进程访问了不在有效范围中的内粗你去与,或以不正确的方式访问了有效地址,那么内核就会终止该进程,并返回“段错误”信息。

  • 可执行文件代码的内存映射称为代码段。(text section)
  • 可执行文件的已初始化全局变量的内存映射,称为数据段。(data section)
  • 包含未初始化全局变量,也就是bss段的零页的内存映射。
  • 用于进程用户空间栈的零页的内存映射
  • 每一个诸如C库或动态连接程序等共享库的代码段、数据段和bss也会被载入进程的地址空间
  • 任何内存映射文件
  • 任何共享内存段
  • 任何匿名的内存映射,比如由malloc()分配的内存

二、内存描述符

内存描述符结构体表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息。

内存描述符由mm_struct结构体表示,定义在文件<linux/sched.h>中。

  1. struct mm_struct {
  2. struct vm_area_struct *mmap; /* list of VMAs 内存区域链表 */
  3. struct rb_root mm_rb; /* VMA形成的红黑树 */
  4. u32 vmacache_seqnum; /* per-thread vmacache */
  5. #ifdef CONFIG_MMU
  6. unsigned long (*get_unmapped_area) (struct file *filp,
  7. unsigned long addr, unsigned long len,
  8. unsigned long pgoff, unsigned long flags);
  9. #endif
  10. unsigned long mmap_base; /* base of mmap area */
  11. unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */
  12. unsigned long task_size; /* size of task vm space */
  13. unsigned long highest_vm_end; /* highest vma end address */
  14. pgd_t * pgd; /* 页全局目录 */
  15. atomic_t mm_users; /* How many users with user space? 使用地址空间的用户数*/
  16. atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) 主使用计数器*/
  17. atomic_long_t nr_ptes; /* PTE page table pages */
  18. #if CONFIG_PGTABLE_LEVELS > 2
  19. atomic_long_t nr_pmds; /* PMD page table pages */
  20. #endif
  21. int map_count; /* number of VMAs 内存区域的个数*/
  22.  
  23. spinlock_t page_table_lock; /* Protects page tables and some counters 页表锁*/
  24. struct rw_semaphore mmap_sem; /* 内存区域信号量 */
  25.  
  26. struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
  27. * together off init_mm.mmlist, and are protected
  28. * by mmlist_lock 所有mm_struct形成的链表
  29. */
  30.  
  31. unsigned long hiwater_rss; /* High-watermark of RSS usage */
  32. unsigned long hiwater_vm; /* High-water virtual memory usage */
  33.  
  34. unsigned long total_vm; /* Total pages mapped 全部页面数目*/
  35. unsigned long locked_vm; /* Pages that have PG_mlocked set 上锁的页面数目*/
  36. unsigned long pinned_vm; /* Refcount permanently increased */
  37. unsigned long shared_vm; /* Shared pages (files) */
  38. unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE */
  39. unsigned long stack_vm; /* VM_GROWSUP/DOWN */
  40. unsigned long def_flags;
  41. unsigned long start_code, end_code, start_data, end_data; /* 代码段开始和停止,数据段开始和停止 */
  42. unsigned long start_brk, brk, start_stack; /* 堆首地址,堆尾,进程栈地址 */
  43. unsigned long arg_start, arg_end, env_start, env_end;
  44.  
  45. unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv 保存的auxv*/
  46.  
  47. /*
  48. * Special counters, in some configurations protected by the
  49. * page_table_lock, in other configurations by being atomic.
  50. */
  51. struct mm_rss_stat rss_stat;
  52.  
  53. struct linux_binfmt *binfmt;
  54.  
  55. cpumask_var_t cpu_vm_mask_var; /* 懒惰(Lazy)TLB交换掩码 */
  56.  
  57. /* Architecture-specific MM context 体系结构特殊数据*/
  58. mm_context_t context;
  59.  
  60. unsigned long flags; /* Must use atomic bitops to access the bits 状态标志*/
  61.  
  62. struct core_state *core_state; /* coredumping support */
  63. #ifdef CONFIG_AIO
  64. spinlock_t ioctx_lock;
  65. struct kioctx_table __rcu *ioctx_table;
  66. #endif
  67. #ifdef CONFIG_MEMCG
  68. /*
  69. * "owner" points to a task that is regarded as the canonical
  70. * user/owner of this mm. All of the following must be true in
  71. * order for it to be changed:
  72. *
  73. * current == mm->owner
  74. * current->mm != mm
  75. * new_owner->mm == mm
  76. * new_owner->alloc_lock is held
  77. */
  78. struct task_struct __rcu *owner;
  79. #endif
  80. struct user_namespace *user_ns;
  81.  
  82. /* store ref to file /proc/<pid>/exe symlink points to */
  83. struct file __rcu *exe_file;
  84. #ifdef CONFIG_MMU_NOTIFIER
  85. struct mmu_notifier_mm *mmu_notifier_mm;
  86. #endif
  87. #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
  88. pgtable_t pmd_huge_pte; /* protected by page_table_lock */
  89. #endif
  90. #ifdef CONFIG_CPUMASK_OFFSTACK
  91. struct cpumask cpumask_allocation;
  92. #endif
  93. #ifdef CONFIG_NUMA_BALANCING
  94. /*
  95. * numa_next_scan is the next time that the PTEs will be marked
  96. * pte_numa. NUMA hinting faults will gather statistics and migrate
  97. * pages to new nodes if necessary.
  98. */
  99. unsigned long numa_next_scan;
  100.  
  101. /* Restart point for scanning and setting pte_numa */
  102. unsigned long numa_scan_offset;
  103.  
  104. /* numa_scan_seq prevents two threads setting pte_numa */
  105. int numa_scan_seq;
  106. #endif
  107. #if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
  108. /*
  109. * An operation with batched TLB flushing is going on. Anything that
  110. * can move process memory needs to flush the TLB when moving a
  111. * PROT_NONE or PROT_NUMA mapped page.
  112. */
  113. bool tlb_flush_pending;
  114. #endif
  115. #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
  116. /* See flush_tlb_batched_pending() */
  117. bool tlb_flush_batched;
  118. #endif
  119. struct uprobes_state uprobes_state;
  120. #ifdef CONFIG_X86_INTEL_MPX
  121. /* address of the bounds directory */
  122. void __user *bd_addr;
  123. #endif
  124. #ifdef CONFIG_HUGETLB_PAGE
  125. atomic_long_t hugetlb_usage;
  126. #endif
  127. struct work_struct async_put_work;
  128. };

mm_struct

mm_users域记录正在使用该地址的进程数目。mm_count域是mm_struct结构体的主引用计数。

mmap和mm_rb这两个不同数据结构体描述的对象是相同的:该地址空间中的全部内存区域。前者以链表形式存放而后者以红-黑树形式存放。

mmap结构体作为链表,利于简单、高效地遍历所有元素。而mm_rb结构体作为红-黑树,更适合搜索指定元素。

所有mm_struct结构体都通过自身的mmlist域连接在一个双向链表中,该链表的首元素是init_mm内存描述符,代表init进程地址空间

操作该链表的时候需要使用mmlist_lock锁来防止并发访问,在<kernel/fork.c>中。

2.1 分配内存描述符

在进程描述符<linux/sched.h>中,mm域存放着该进程使用的内存描述符,所以current->mm便指向当前进程的内存描述符。

2.2 撤销内存描述符

当进程退出时,内核会调用定义在kernel/exit.c中的exit_mm()函数,该函数执行一些常规的撤销工作,同时更新一些统计量。

该函数调用mmput()函数减少内存描述符中的mm_users用户计数,如果降到0。调用mmdrop函数,减少mm_count使用计数。

2.3 mm_struct与内核线程

内核线程没有进程地址空间,也没有相关的内存描述符。

三、虚拟内存区域

vm_area_struct结构体,定义在文件<linux/mm_types.h>中。它描述了指定地址空间内连续区域间上的一个独立内存范围。

内核将每个内存区域作为一个单独的内存对象管理,每个内存区域都拥有一致的属性。

  1. /*
  2. * This struct defines a memory VMM memory area. There is one of these
  3. * per VM-area/task. A VM area is any part of the process virtual memory
  4. * space that has a special rule for the page-fault handlers (ie a shared
  5. * library, the executable area etc).
  6. */
  7. struct vm_area_struct {
  8. /* The first cache line has the info for VMA tree walking. */
  9.  
  10. unsigned long vm_start; /* Our start address within vm_mm. 区间的首地址*/
  11. unsigned long vm_end; /* The first byte after our end address
  12. within vm_mm. 区间的尾地址*/
  13.  
  14. /* linked list of VM areas per task, sorted by address */
  15. struct vm_area_struct *vm_next, *vm_prev; /* VMA链表 */
  16.  
  17. struct rb_node vm_rb; /* 树上该VMA的节点 */
  18.  
  19. /*
  20. * Largest free memory gap in bytes to the left of this VMA.
  21. * Either between this VMA and vma->vm_prev, or between one of the
  22. * VMAs below us in the VMA rbtree and its ->vm_prev. This helps
  23. * get_unmapped_area find a free area of the right size.
  24. */
  25. unsigned long rb_subtree_gap;
  26.  
  27. /* Second cache line starts here. */
  28.  
  29. struct mm_struct *vm_mm; /* The address space we belong to. 相关的mm_struct结构体*/
  30. pgprot_t vm_page_prot; /* Access permissions of this VMA. */
  31. unsigned long vm_flags; /* Flags, see mm.h. 标志位*/
  32.  
  33. /*
  34. * For areas with an address space and backing store,
  35. * linkage into the address_space->i_mmap interval tree.
  36. *
  37. * For private anonymous mappings, a pointer to a null terminated string
  38. * in the user process containing the name given to the vma, or NULL
  39. * if unnamed.
  40. */
  41. union {
  42. struct {
  43. struct rb_node rb;
  44. unsigned long rb_subtree_last;
  45. } shared;
  46. const char __user *anon_name;
  47. };
  48.  
  49. /*
  50. * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
  51. * list, after a COW of one of the file pages. A MAP_SHARED vma
  52. * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
  53. * or brk vma (with NULL file) can only be in an anon_vma list.
  54. */
  55. struct list_head anon_vma_chain; /* Serialized by mmap_sem &
  56. * page_table_lock */
  57. struct anon_vma *anon_vma; /* Serialized by page_table_lock 匿名VMA对象*/
  58.  
  59. /* Function pointers to deal with this struct. 相关的操作表*/
  60. const struct vm_operations_struct *vm_ops;
  61.  
  62. /* Information about our backing store: */
  63. unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
  64. units, *not* PAGE_CACHE_SIZE 文件中的偏移量*/
  65. struct file * vm_file; /* File we map to (can be NULL). 被映射的文件(如果存在)*/
  66. void * vm_private_data; /* was vm_pte (shared mem) 私有数据*/
  67.  
  68. #ifndef CONFIG_MMU
  69. struct vm_region *vm_region; /* NOMMU mapping region */
  70. #endif
  71. #ifdef CONFIG_NUMA
  72. struct mempolicy *vm_policy; /* NUMA policy for the VMA */
  73. #endif
  74. struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
  75. };

vm_area_struct

每个内存描述符都对应于进程地址空间中的唯一区间。vm_start域指向区间的首地址,vm_end域指向区间的尾地址之后的第一个字节。vm_end-vm_start就是区间的长度。

vm_mm域指向和VMA相关的mm_struct结构体,VMA对其香瓜你的mm_struct。

3.1 VMA标志

VMA标志是一种标志位,定义在<linux/mm.h>。在vm_flags域内,包含了域所包含的页面的行为和信息。

  1. /*
  2. * vm_flags in vm_area_struct, see mm_types.h.
  3. */
  4. #define VM_NONE 0x00000000
  5.  
  6. #define VM_READ 0x00000001 /* currently active flags 页面可读*/
  7. #define VM_WRITE 0x00000002 /* 页面可写 */
  8. #define VM_EXEC 0x00000004 /* 页面可执行 */
  9. #define VM_SHARED 0x00000008 /* 页面可共享 */
  10.  
  11. /* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */
  12. #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc VM_READ标志可被设置*/
  13. #define VM_MAYWRITE 0x00000020
  14. #define VM_MAYEXEC 0x00000040
  15. #define VM_MAYSHARE 0x00000080
  16.  
  17. #define VM_GROWSDOWN 0x00000100 /* general info on the segment 区域可向下增长*/
  18. #define VM_UFFD_MISSING 0x00000200 /* missing pages tracking 区域可向上增长*/
  19. #define VM_PFNMAP 0x00000400 /* Page-ranges managed without "struct page", just pure PFN */
  20. #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. 区域映射一个不可写文件*/
  21. #define VM_UFFD_WP 0x00001000 /* wrprotect pages tracking */
  22.  
  23. #define VM_LOCKED 0x00002000 /* 区域中的页面被锁定 */
  24. #define VM_IO 0x00004000 /* Memory mapped I/O or similar 区域映射设备I/O控件*/
  25.  
  26. /* Used by sys_madvise() */
  27. #define VM_SEQ_READ 0x00008000 /* App will access data sequentially 页面可能会被连续访问*/
  28. #define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads 页面可能会被随机访问*/
  29.  
  30. #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork 区域不能在fork时被拷贝*/
  31. #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() 区域不能通过mremap()增加*/
  32. #define VM_LOCKONFAULT 0x00080000 /* Lock the pages covered when they are faulted in */
  33. #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object 该区域是一个记账VM对象*/
  34. #define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */
  35. #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM 区域使用了hugetlb页面*/
  36. #define VM_ARCH_1 0x01000000 /* Architecture-specific flag */
  37. #define VM_ARCH_2 0x02000000
  38. #define VM_DONTDUMP 0x04000000 /* Do not include in the core dump */
  39.  
  40. #ifdef CONFIG_MEM_SOFT_DIRTY
  41. # define VM_SOFTDIRTY 0x08000000 /* Not soft dirty clean area */
  42. #else
  43. # define VM_SOFTDIRTY
  44. #endif
  45.  
  46. #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
  47. #define VM_HUGEPAGE 0x20000000 /* MADV_HUGEPAGE marked this vma */
  48. #define VM_NOHUGEPAGE 0x40000000 /* MADV_NOHUGEPAGE marked this vma */
  49. #define VM_MERGEABLE 0x80000000 /* KSM may merge identical pages */
  50.  
  51. #if defined(CONFIG_X86)
  52. # define VM_PAT VM_ARCH_1 /* PAT reserves whole VMA at once (x86) */
  53. #elif defined(CONFIG_PPC)
  54. # define VM_SAO VM_ARCH_1 /* Strong Access Ordering (powerpc) */
  55. #elif defined(CONFIG_PARISC)
  56. # define VM_GROWSUP VM_ARCH_1
  57. #elif defined(CONFIG_METAG)
  58. # define VM_GROWSUP VM_ARCH_1
  59. #elif defined(CONFIG_IA64)
  60. # define VM_GROWSUP VM_ARCH_1
  61. #elif !defined(CONFIG_MMU)
  62. # define VM_MAPPED_COPY VM_ARCH_1 /* T if mapped copy of data (nommu mmap) */
  63. #endif

VMA标志

3.2 VMA操作

vm_area_struct结构体中的vm_ops域指向与指定内存区域相关的操作函数表,内核使用表中的方法操作VMA。

操作函数表由vm_operations_struct结构体表示,定义在文件<linux/mm.h>中:

  1. /*
  2. * These are the virtual MM functions - opening of an area, closing and
  3. * unmapping it (needed to keep files on disk up-to-date etc), pointer
  4. * to the functions called when a no-page or a wp-page exception occurs.
  5. */
  6. struct vm_operations_struct {
  7. void (*open)(struct vm_area_struct * area);
  8. void (*close)(struct vm_area_struct * area);
  9. int (*mremap)(struct vm_area_struct * area);
  10. int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
  11. int (*pmd_fault)(struct vm_area_struct *, unsigned long address,
  12. pmd_t *, unsigned int flags);
  13. void (*map_pages)(struct vm_area_struct *vma, struct vm_fault *vmf);
  14.  
  15. /* notification that a previously read-only page is about to become
  16. * writable, if an error is returned it will cause a SIGBUS */
  17. int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
  18.  
  19. /* same as page_mkwrite when using VM_PFNMAP|VM_MIXEDMAP */
  20. int (*pfn_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
  21.  
  22. /* called by access_process_vm when get_user_pages() fails, typically
  23. * for use by special VMAs that can switch between memory and hardware
  24. */
  25. int (*access)(struct vm_area_struct *vma, unsigned long addr,
  26. void *buf, int len, int write);
  27.  
  28. /* Called by the /proc/PID/maps code to ask the vma whether it
  29. * has a special name. Returning non-NULL will also cause this
  30. * vma to be dumped unconditionally. */
  31. const char *(*name)(struct vm_area_struct *vma);
  32.  
  33. #ifdef CONFIG_NUMA
  34. /*
  35. * set_policy() op must add a reference to any non-NULL @new mempolicy
  36. * to hold the policy upon return. Caller should pass NULL @new to
  37. * remove a policy and fall back to surrounding context--i.e. do not
  38. * install a MPOL_DEFAULT policy, nor the task or system default
  39. * mempolicy.
  40. */
  41. int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
  42.  
  43. /*
  44. * get_policy() op must add reference [mpol_get()] to any policy at
  45. * (vma,addr) marked as MPOL_SHARED. The shared policy infrastructure
  46. * in mm/mempolicy.c will do this automatically.
  47. * get_policy() must NOT add a ref if the policy at (vma,addr) is not
  48. * marked as MPOL_SHARED. vma policies are protected by the mmap_sem.
  49. * If no [shared/vma] mempolicy exists at the addr, get_policy() op
  50. * must return NULL--i.e., do not "fallback" to task or system default
  51. * policy.
  52. */
  53. struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
  54. unsigned long addr);
  55. #endif
  56. /*
  57. * Called by vm_normal_page() for special PTEs to find the
  58. * page for @addr. This is useful if the default behavior
  59. * (using pte_page()) would not find the correct page.
  60. */
  61. struct page *(*find_special_page)(struct vm_area_struct *vma,
  62. unsigned long addr);
  63. };
  64.  
  65. void (*open)(struct vm_area_struct * area);
  66. 当制定的内存区域被加入到一个地址空间时,改函数被调用
  67. void (*close)(struct vm_area_struct * area);
  68. 当制定的内存区域从地址空间删除时,该函数被调用
  69. int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
  70. 当没有出现在物理内存中的页面被访问时,改函数被页面故障处理调用
  71. int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
  72. 当某个页面为只读页面时,该函数被页面故障处理调用
  73. int (*access)(struct vm_area_struct *vma, unsigned long addr,
  74. void *buf, int len, int write);
  75. get_user_pages()函数调用失败时,该函数被access_process_vm()函数调用

VMA操作

3.3 内存区域的树型结构和内存区域的链表结构

vm_area_struct结构体通过自身的vm_next域连入链表,所有区域按地址增长方向排序,mmap域指向链表中第一个内存区域,链中最后一个结构体指向空。

3.4 实际使用中的内存区域

可以使用/proc文件系统和pmap工具查看给定进程的内存空间和其中所含的内存区域。

四、操作内存区域

内核市场需要在某个内存区域上执行一些操作,他们都声明在<linux/mm.h>中。

4.1 find_vma()

为了找到给定的内存地址属于哪个内存区域,内核提供了find_vma()函数。函数定义在<mm/mmap.c>中。

  1. struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr);
  2. 在指定的地址空间中搜索第一个vm_end大于addr的内存区域。
  3. 如果没有发现这样的区域,该函数返回NULL。否则返回指向匹配的内存区域的vm_area_struct结构体指针。

find_vma

4.2 find_vma_prev()

与find_vma工作方式相同,返回第一个小于addr的VMA,该函数定义和声明分别在文件mm/mmap.c中和文件<linux/mm.h>中

  1. struct vm_area_struct *find_vma_prev(struct mm_struct *mm, unsigned long addr, struct vm_area_struct **pprev)
  2. pprev参数存放指向先于addrVMA指针

find_vma_prev

4.3 find_vma_intersection()

返回第一个指定地址区间相交的VMA,内联函数,在<linux/mm.h>中

  1. stati inline struct vm_area_struct *find_vma_intersection(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr) {
  2. struct vm_area_struct *vma;
  3. vma = find_vma(mm, start_addr);
  4. if(vma && end_addr <= vma->vm_start)
  5. vma = NULL;
  6. return vma;
  7. }
  8. 第一个参数mm是要搜索的地址空间,start_addr是区间开始首地址,end_addr是区间的尾位置。
  9. 如果返回NULL,没有发现这样的区域。如果返回有效VMA,则只有在该VMA起始位置于给定的地址区间结束位置之前,才将其返回。如果VMA起始位置大于指定地址范围的结束位置,则该函数返回NULL

find_vma_intersection

五、mmap()和do_mmap():创建地址区间

内核使用do_mmap()函数创建一个新的线性地址区间。定义在文件<linux/mm.h>中。

  1. unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset)
  2. file:指定的文件,offset:偏移量,len:长度

do_mmap

如果file参数是NULL,offset也为0,代表这次映射没有文件相关,是匿名映射。

addr是可选参数,指定搜索空闲区域的起始位置。

prot参数指定内存区域中页面的访问权限,标志位在<asm/mman.h>中,不同体系结构有所不同。

  1. PROT_READ:对应于VM_READ
  2. PROT_WRITE:对应于VM_WRITE
  3. PROT_EXEC:对应于VM_EXEC
  4. PROT_NONE:不可被访问

页保护标志

flag参数指定了VMA标志,这些标志指定类型并该表映射的行为,也在文件<asm/mman.h>中定义。

  1. MAP_SHARED:映射可以被共享
  2. MAP_PRIVATE:映射不能被共享
  3. MAP_FIXED:新区间必须开始于指定地址addr
  4. MAP_ANONYMOUS:映射不是file-backed,而是匿名的
  5. MAP_GROWSDOWN:对应于VM_GROWSDOWN
  6. MAP_DENYWRITE:对应于VM_DENYWRITE
  7. MAP_EXECUTABLE:对应于VM_EXECUTABLE
  8. MAP_LOCKED:对应于VM_LOCKED
  9. MAP_NORESERVE:不需要为映射保留空间
  10. MAP_POPULATE:填充页表
  11. MAP_NONBLOCK:在I/O操作上不堵塞

页保护标志

空户空间可以通过mmap()系统调用获取内核函数do_mmap()功能,mmap调用定义如下:

  1. void *mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoff)

mmap2

六、munmap()和do_menmap():删除地址区间

do_munmap()函数从特定的进程地址空间中删除指定地址区间,该函数定义在文件<linux/mm.h>

  1. int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
  2. mm:要删除区域所在的地址空间
  3. start:要删除的开始地址
  4. len:地址长度
  5. 成功:,否则负的错误码

do_munmap

系统调用munmap()给用户提供了删除指定地址的方法,和mmap相反。

  1. int munmap(void *start, size_t length)

munmap

七、页表

地址转换需要将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表,而页表项则指向下一级别的页表或指向最终的物理页面。

Linux使用三级页表完成地址转换。使用三级页表结构可以利用“最大公约数”的思想,一种简单的体系结构。

顶级页表是全局目录(PGD)

二级页表是中间页目录(PMD)

最后一级页表指向物理页面。

页表队以ing的结构体依赖于具体的体系结构,所以定义在文件<asm/page.h>中。

Linux内核设计与实现 总结笔记(第十五章)进程地址空间的更多相关文章

  1. Linux内核设计与实现 总结笔记(第五章)系统调用

    系统调用 内核提供了用户进程和内核交互的接口,使得应用程序可以受限制的访问硬件设备. 提供这些接口主要是为了保证系统稳定可靠,避免应用程序恣意妄行. 一.内核通信 系统调用在用户空间进程和硬件设备之间 ...

  2. 《Linux内核设计与实现》读书笔记(十五)- 进程地址空间(kernel 2.6.32.60)

    进程地址空间也就是每个进程所使用的内存,内核对进程地址空间的管理,也就是对用户态程序的内存管理. 主要内容: 地址空间(mm_struct) 虚拟内存区域(VMA) 地址空间和页表 1. 地址空间(m ...

  3. Linux内核设计与实现 总结笔记(第七章)中断和中断处理

    中断和中断处理 处理器的速度跟外围硬件设备的速度往往不再一个数量级上,因此,如果内核采取让处理器向硬件发出一个请求. 然后专门等待回应的办法,如果专门等待回应,明显太慢.所以等待期间可以处理其他事务, ...

  4. Linux内核设计与实现 总结笔记(第六章)内核数据结构

    内核数据结构 Linux内核实现了这些通用数据结构,而且提倡大家在开发时重用. 内核开发者应该尽可能地使用这些数据结构,而不要自作主张的山寨方法. 通用的数据结构有以下几种:链表.队列.映射和二叉树 ...

  5. Linux内核设计与实现 总结笔记(第四章)进程调度

    进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间. 调度程序没有太复杂的原理,最大限度地利用处理器时间的原则是,只要有可以执行的进程,那么就总会有进程正在执行. 一.多任务 多任 ...

  6. Linux内核设计与实现 总结笔记(第三章)进程

    进程管理 进程:处于执行期的程序. 线程:在进程中活动的对象 虚拟机制 虚拟处理器:多个进程分享一个处理器 虚拟内存:多个线程共享虚拟内存 一.进程描述符和任务结构 进程存放在双向循环链表中(队列), ...

  7. 把握linux内核设计思想(十三):内存管理之进程地址空间

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet.文章仅供学习交流,请勿用于商业用途] 进程地址空间由进程可寻址的虚拟内存组成,Linux 的虚拟地址空间为0~4G字 ...

  8. Linux内核设计与实现 总结笔记(第十一章)定时器和时间管理

    时间管理在内核中占用非常重要的地位,内核中有大量的函数都需要基于时间驱动的,内核对相对时间和绝对时间都非常需要. 一.内核中的时间概念 内核必须在硬件的帮助下才能计算和管理时间,系统定时器以某种频率自 ...

  9. Linux内核设计与实现 总结笔记(第十三章)虚拟文件系统

    一.通用文件系统接口 Linux通过虚拟文件系统,使得用户可以直接使用open().read().write()访问文件系统,这种协作性和泛型存取成为可能. 不管文件系统是什么,也不管文件系统位于何种 ...

  10. 《Linux内核设计与实现》课本第十八章自学笔记——20135203齐岳

    <Linux内核设计与实现>课本第十八章自学笔记 By20135203齐岳 通过打印来调试 printk()是内核提供的格式化打印函数,除了和C库提供的printf()函数功能相同外还有一 ...

随机推荐

  1. TCP中SYN洪水攻击

    在查看TCP标识位SYN时,顺便关注了一下SYN Flood,从网上查阅一些资料加以整理,SYN洪水攻击利用TCP三次握手. 1.SYN洪水介绍 当一个系统(客户端C)尝试和一个提供了服务的系统(服务 ...

  2. 3D打印技术的学习

    1. 我们使用3D建模软件:123Ddesign来设计 123D design软件保存格式有2种,分别为123dx和stl格式 123dx格式:选择菜单栏中“Save”下的“To my compute ...

  3. pandas中.value_counts()的用法

    原文链接:https://www.jianshu.com/p/f773b4b82c66 value_counts()是一种查看表格某列中有多少个不同值的快捷方法,并计算每个不同值有在该列中有多少重复值 ...

  4. python 使用 with open() as 读写文件

    读文件: 要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符: >>> f = open('E:\python\python\test.tx ...

  5. python每日一练:0000题

    **第 0000 题:**将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果. 类似于图中效果 示例代码: from PIL import Image,Imag ...

  6. MySql-Mysql技术内幕~SQL编程学习笔记(N)

    1._rowid 类似Oracle的rowid mysql> ; +-------+----+----------------+-------------+---------------+--- ...

  7. [LeetCode] 212. 单词搜索 II

    题目链接:https://leetcode-cn.com/problems/word-search-ii/ 题目描述: 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在 ...

  8. PCIe事务层の详解(一)

    PCIe总线的通信机制:当一个设备要想另一个设备进行读取通信时,请求方requester需要向另一个设备发送请求request,靶向方作为事件完成方completer,以complete Packet ...

  9. Django基础命令

    创建工程 django-admin startproject 项目名创建应用 django-admin startapp 应用名 生成迁移 python3 manage.py makemigratio ...

  10. VB中IIF函数

    IIf 函数语法:IIf(表达式, 真值部分, 假值部分)根据表达式的值,表达式为真时,返回真值部分,表达式为假时,返回假部分.如:iif(a>0, "对","错& ...