unsignedlong vm_start; /* Our start address within vm_mm. */ unsignedlong vm_end; /* The first byte after our end address within vm_mm. */ // VMA 区域的具体属性 pgprot_t vm_page_prot; unsignedlong vm_flags;
structanon_vma *anon_vma;/* Serialized by page_table_lock */ structfile * vm_file;/* File we map to (can be NULL). */ unsignedlong vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE units */ void * vm_private_data; /* was vm_pte (shared mem) */ /* Function pointers to deal with this struct. */ conststructvm_operations_struct *vm_ops;
// https://elixir.bootlin.com/linux/v7.1-rc7/source/include/linux/mm.h#L768 structvm_operations_struct { /** * @open: Called when a VMA is remapped, split or forked. Not called * upon first mapping a VMA. * Context: User context. May sleep. Caller holds mmap_lock. */ void (*open)(struct vm_area_struct *vma); // 当虚拟内存被加入到进程的虚拟地址空间的时候会被调用 /** * @close: Called when the VMA is being removed from the MM. * Context: User context. May sleep. Caller holds mmap_lock. */ void (*close)(struct vm_area_struct *vma); // 当虚拟内存从进程的虚拟地址空间中删除的时候会被调用 /** * @mapped: Called when the VMA is first mapped in the MM. Not called if * the new VMA is merged with an adjacent VMA. * * The @vm_private_data field is an output field allowing the user to * modify vma->vm_private_data as necessary. * * ONLY valid if set from f_op->mmap_prepare. Will result in an error if * set from f_op->mmap. * * Returns %0 on success, or an error otherwise. On error, the VMA will * be unmapped. * * Context: User context. May sleep. Caller holds mmap_lock. */ int (*mapped)(unsignedlong start, unsignedlong end, pgoff_t pgoff, conststruct file *file, void **vm_private_data); /* Called any time before splitting to check if it's allowed */ int (*may_split)(struct vm_area_struct *vma, unsignedlong addr); int (*mremap)(struct vm_area_struct *vma); /* * Called by mprotect() to make driver-specific permission * checks before mprotect() is finalised. The VMA must not * be modified. Returns 0 if mprotect() can proceed. */ int (*mprotect)(struct vm_area_struct *vma, unsignedlong start, unsignedlong end, unsignedlong newflags); vm_fault_t (*fault)(struct vm_fault *vmf); vm_fault_t (*huge_fault)(struct vm_fault *vmf, unsignedint order); vm_fault_t (*map_pages)(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff); unsignedlong(*pagesize)(struct vm_area_struct *vma);
/* notification that a previously read-only page is about to become * writable, if an error is returned it will cause a SIGBUS */ vm_fault_t (*page_mkwrite)(struct vm_fault *vmf);
/* same as page_mkwrite when using VM_PFNMAP|VM_MIXEDMAP */ vm_fault_t (*pfn_mkwrite)(struct vm_fault *vmf);
/* called by access_process_vm when get_user_pages() fails, typically * for use by special VMAs. See also generic_access_phys() for a generic * implementation useful for any iomem mapping. */ int (*access)(struct vm_area_struct *vma, unsignedlong addr, void *buf, int len, int write);
/* Called by the /proc/PID/maps code to ask the vma whether it * has a special name. Returning non-NULL will also cause this * vma to be dumped unconditionally. */ constchar *(*name)(struct vm_area_struct *vma);
#ifdef CONFIG_NUMA /* * set_policy() op must add a reference to any non-NULL @new mempolicy * to hold the policy upon return. Caller should pass NULL @new to * remove a policy and fall back to surrounding context--i.e. do not * install a MPOL_DEFAULT policy, nor the task or system default * mempolicy. */ int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
/* * get_policy() op must add reference [mpol_get()] to any policy at * (vma,addr) marked as MPOL_SHARED. The shared policy infrastructure * in mm/mempolicy.c will do this automatically. * get_policy() must NOT add a ref if the policy at (vma,addr) is not * marked as MPOL_SHARED. vma policies are protected by the mmap_lock. * If no [shared/vma] mempolicy exists at the addr, get_policy() op * must return NULL--i.e., do not "fallback" to task or system default * policy. */ structmempolicy *(*get_policy)(structvm_area_struct *vma, unsignedlongaddr, pgoff_t *ilx); #endif #ifdef CONFIG_FIND_NORMAL_PAGE /* * Called by vm_normal_page() for special PTEs in @vma at @addr. This * allows for returning a "normal" page from vm_normal_page() even * though the PTE indicates that the "struct page" either does not exist * or should not be touched: "special". * * Do not add new users: this really only works when a "normal" page * was mapped, but then the PTE got changed to something weird (+ * marked special) that would not make pte_pfn() identify the originally * inserted page. */ structpage *(*find_normal_page)(structvm_area_struct *vma, unsignedlongaddr); #endif/* CONFIG_FIND_NORMAL_PAGE */ #ifdef CONFIG_USERFAULTFD conststructvm_uffd_ops *uffd_ops; #endif };
// 开始加载 segments elf_ppnt = elf_phdata; for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) { char *elf_interpreter;
if (elf_ppnt->p_type == PT_GNU_PROPERTY) { elf_property_phdata = elf_ppnt; continue; }
if (elf_ppnt->p_type != PT_INTERP) continue;
/* * This is the program interpreter used for shared libraries - * for now assume that this is an a.out format binary. */ retval = -ENOEXEC; if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2) goto out_free_ph;