2.4 linux存储管理-越界访问
来源:互联网 发布:遗传算法图像分割 编辑:程序博客网 时间:2024/05/23 19:26
当我们通过页式存储管理机制将线性地址转换成物理地址时,如果这个过程由于遇到某种阻碍而使得CPU无法访问到相应的物理单元,映射便失败了。
映射失败时,CPU会触发一种异常,这种异常称之为缺页异常(page fault exception),进而执行页面异常处理程序。
失败的原因:
1)虚拟、物理映射尚未建立
2)物理页面被swap off
3)访问权限不对应(想要写只读权限内存)
可能还有别的原因
CPU在发生页面异常时,会触发page_fault_exception处理,最后执行do_page_fault()
do_page_fault的部分代码(开头):
106 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
107 {
108 struct task_struct *tsk;
109 struct mm_struct *mm;
110 struct vm_area_struct * vma;
111 unsigned long address;
112 unsigned long page;
113 unsigned long fixup;
114 int write;
115 siginfo_t info;
116
117 /* get the address */
118 __asm__("movl %%cr2,%0":"=r" (address));
119
120 tsk = current;
121
122 /*
123 * We fault-in kernel-space virtual memory on-demand. The
124 * 'reference' page table is init_mm.pgd.
58
125 *
126 * NOTE! We MUST NOT take any locks for this case. We may
127 * be in an interrupt or a critical region, and should
128 * only copy the information from the master page table,
129 * nothing more.
130 */
131 if (address >= TASK_SIZE)
132 goto vmalloc_fault;
133
134 mm = tsk->mm;
135 info.si_code = SEGV_MAPERR;
136
137 /*
138 * If we're in an interrupt or have no user
139 * context, we must not take the fault..
140 */
141 if (in_interrupt() || !mm)
142 goto no_context;
143
144 down(&mm->mmap_sem);
145
146 vma = find_vma(mm, address);
147 if (!vma)
148 goto bad_area;
149 if (vma->vm_start <= address)
150 goto good_area;
151 if (!(vma->vm_flags & VM_GROWSDOWN))
152 goto bad_area;
(参见 arch/i386/mm/fault.c)
代码说明:
1.获取产生缺页异常的虚拟地址(线性地址)。产生缺页异常的虚拟地址被保存在CR2寄存器中,由于c语言无法读取CR2寄存器,需要使用gcc内嵌汇编实现。2. 内核中断/异常机制还会传回两个参数:struct pt_regs *regs, unsigned long error_code,regs指向寄存器的副本(保存“现场”),error_code指明映射失败的原因。3. 内核中可以使用current(宏)取得当前进程的task结构体,然后我们可以获取当前进程的mm_struct(保存虚存管理和映射相关信息),CPU的映射过程不影响mm_struct结构,但是mm_struct描述了这种映射。4. 进程出错:find_vma返回寻找到的第一个末尾地址大于address的vma,根据返回的vma结果进一步判断错误原因。4.1 第一种 goto bad_area:没有找到合适的vma,说明address过大,访问的地址属于系统空间4.2 goto good_area:说明找到合适vma,映射已经建立,原因需要进一步查找除了前面两种情况,还有可能落在vma之间的洞里面4.3 第一种空洞:堆栈区下面的大空洞堆栈区的vma的vm_flags有VM_GROWSDOWN这个标志位(这种情况的处理,也是goto good_area,里面会进一步判断)4.4 第二种空洞:vma之间的小空洞
5. 出错特殊情况
中断处理程序出错(程序能够检测):
若in_interrupt()返回非0,说明中断处理程序出错
mm_struct为空(程序不能检测出):
因为mm_struct为空,说明进程的映射尚未建立,因而不可能与当前进程有关,而in_interrupt()又返回0,说明中断异常处理中出错,不过该错误in_interrupt()无法检测出来
do_page_fault的部分代码(bad_area处理):
220 /*
221 * Something tried to access memory that isn't in our memory map..
222 * Fix it, but check if it's kernel or user first..
223 */
224 bad_area:
225 up(&mm->mmap_sem);
226
227 bad_area_nosemaphore:
228 /* User mode accesses just cause a SIGSEGV */
229 if (error_code & 4) {
230 tsk->thread.cr2 = address;
231 tsk->thread.error_code = error_code;
232 tsk->thread.trap_no = 14;
233 info.si_signo = SIGSEGV;
234 info.si_errno = 0;
235 /* info.si_code has been set above */
236 info.si_addr = (void *)address;
237 force_sig_info(SIGSEGV, &info, tsk);
238 return;
239 }
error_code的取值和含义:
96 /*
97 * This routine handles page faults. It determines the address,
98 * and the problem, and then passes it off to one of the appropriate
99 * routines.
100 *
101 * error_code:
102 * bit 0 == 0 means no page found, 1 means protection fault
103 * bit 1 == 0 means read, 1 means write
104 * bit 2 == 0 means kernel, 1 means user-mode
105 */
阅读全文
0 0
- 2.4 linux存储管理-越界访问
- 【存储管理】越界访问与用户堆栈的扩展
- 越界访问
- 越界访问
- Linux越界访问/用户栈扩展/页面周转
- 小心访问越界
- 内存访问越界
- 【转】内存访问越界
- 内存访问越界
- 内存访问越界
- 内存访问越界
- 内存访问越界
- 内存访问越界问题
- 数组访问越界问题
- 数组访问越界问题
- 访问内存越界
- c++内存访问越界
- gflags调试访问越界
- 算法<Next Permutation问题>
- 1056. Mice and Rice (25)
- golang 空指针
- 性能分析、调优的概念及手段
- 基于Docker、Jenkins和Saltstack的持续部署方案
- 2.4 linux存储管理-越界访问
- hive简介
- bzoj2565manacher算法
- Flutter学习之旅(三)----Flutter常见问题FAQ,看完之后不再是Flutter小白
- CGI --fastCGI
- PHP中==和===的区别在哪?
- Struts2 struts2基本流程与配置
- CC2640R2F开发环境搭建
- (4)bootstrap标签页