linux情景分析第二章-----存储管理(2)

本文详细分析了Linux内核中页面异常的处理机制,包括越界访问时的页异常、页框回收算法(PFRA)。在页异常处理中,`do_page_fault`函数起关键作用,它会检查异常地址是否在进程线性空间内,并通过`handle_mm_fault`进行分页处理。PFRA用于回收物理内存,通过kswapd内核线程定期执行,确保有足够的空闲页。页面按状态分为不可回收、可交换、可同步和可丢弃页,通过LRU算法判断页面的活跃程度来决定回收策略。
摘要由CSDN通过智能技术生成

2.4越界访问

linux中的虚拟地址通过PGD,PTE等映射到物理地址。但当这个映射过程无法正常映射时候,就会报错,产生page fault exception。那么什么时候会无法正常呢?

  • 编程错误。程序使用了不存在的地址
  • 不是编程错误,linux的请求调页机制。即:当进程运行时,linux并不将全部的资源分配给进程,而是仅分配当前需要的这一部分,当进程需要另外的资源的时候(这时候就会产生缺页异常),linux再分配这部分。

 编程错误linux肯定不会手软的,直接弄死进程。请求调页机制,linux会申请页的。

 

当MMU对不存在的虚拟地址进行映射的时候,会产生异常,__dabt_usr: __dabt_svc。 他们都会调用do_DataAbort。

__dabt_usr:
	usr_entry
	kuser_cmpxchg_check

	@
	@ Call the processor-specific abort handler:
	@
	@  r2 - aborted context pc
	@  r3 - aborted context cpsr
	@
	@ The abort handler must return the aborted address in r0, and
	@ the fault status register in r1.                           //说明了调用do_DataAbort时候传递给他的参数。  r0,r1,
	@
#ifdef MULTI_DABORT
	ldr	r4, .LCprocfns
	mov	lr, pc
	ldr	pc, [r4, #PROCESSOR_DABT_FUNC]
#else
	bl	CPU_DABORT_HANDLER
#endif

	@
	@ IRQs on, then call the main handler
	@
	enable_irq
	mov	r2, sp                                           //参数r2
	adr	lr, ret_from_exception
	b	do_DataAbort                   //调用do_DataAbort
ENDPROC(__dabt_usr)


do_DataAbor根据川进来的参数调用 inf->fn ,在这里就是 do_page_fault

asmlinkage void __exception
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
	const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6);
	struct siginfo info;

	if (!inf->fn(addr, fsr, regs))
		return;

	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
		inf->name, fsr, addr);

	info.si_signo = inf->sig;
	info.si_errno = 0;
	info.si_code  = inf->code;
	info.si_addr  = (void __user *)addr;
	arm_notify_die("", regs, &info, fsr, 0);
}


 

do_page_fault函数是页异常的重要函数:

ps:因为在,__dabt_usr: __dabt_svc这两种情况下都会调用do_DataAbort函数,然后调用do_page_fault,所以调用do_page_fault可能是在内核空间,也可能是在用户空间。在内核空间可能会是 进程通过系统调用,中断等进入的,也可能进程本来是内核线程。所以在do_page_fault中要行进判断的。到底是从哪里发生的异常。

一下函数的分析大部分参考了《深入linux内核》书中的 第9章。

static int __kprobes                               //__kprobes标志应该是调试的一种东西,等以后再专门研究一下。
do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
	struct task_struct *tsk;
	struct mm_struct *mm;
	int fault, sig, code;

	if (notify_page_fault(regs, fsr))       //这个函数是专门和上面的__kprobes对应的,调试的东西
		return 0;

	tsk = current;
	mm  = tsk->mm;                          //将出现页异常的进程的  的进程描述符 赋给tsk,内存描述符赋给mm
 
	/*
	 * If we're in an interrupt or have no user
	 * context, we must not take the fault..
	 */
	if (in_atomic() || !mm)                //判断发生发生异常的,in_atomic判断是否是在 原子操作中:中断程序,可延迟函数,禁用内核抢占的临界区。   !mm  判断进程是否是内核线程。参照博客线程调度的文章。
		goto no_context;              //如果缺页是发生在这些情况下,那么就要特
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值