📄 015_mm_oom_kill_c.html
字号:
<html lang="zh-CN" xmlns:gdoc=""> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <style type="text/css">/* default css */table { font-size: 1em; line-height: inherit;}div, address, ol, ul, li, option, select { margin-top: 0px; margin-bottom: 0px;}p { margin: 0px;}body { margin: 0px; padding: 0px; font-family: Verdana, sans-serif; font-size: 10pt; background-color: #ffffff;}h6 { font-size: 10pt }h5 { font-size: 11pt }h4 { font-size: 12pt }h3 { font-size: 13pt }h2 { font-size: 14pt }h1 { font-size: 16pt }blockquote {padding: 10px; border: 1px #DDD dashed }a img {border: 0}div.google_header, div.google_footer { position: relative; margin-top: 1em; margin-bottom: 1em;}/* end default css */ /* default print css */ @media print { body { padding: 0; margin: 0; } div.google_header, div.google_footer { display: block; min-height: 0; border: none; } div.google_header { flow: static(header); } /* used to insert page numbers */ div.google_header::before, div.google_footer::before { position: absolute; top: 0; } div.google_footer { flow: static(footer); } /* always consider this element at the start of the doc */ div#google_footer { flow: static(footer, start); } span.google_pagenumber { content: counter(page); } span.google_pagecount { content: counter(pages); } } @page { @top { content: flow(header); } @bottom { content: flow(footer); } } /* end default print css */ /* custom css *//* end custom css */ /* ui edited css */ body { font-family: Verdana; font-size: 10.0pt; line-height: normal; background-color: #ffffff; } .documentBG { background-color: #ffffff; } /* end ui edited css */</style> </head> <body revision="dcbsxfpf_56f79p8pgf:5"> <table align=center cellpadding=0 cellspacing=0 height=5716 width=768>
<tbody>
<tr>
<td height=5716 valign=top width=100%>
<pre>2006-5-26 <br>mm/oom_kill.c<br>*<br>* 忙,并且忙了很久,占有的少,和权利大的靠边,并毫不谦让,直接出手的有更<br>* 多生还机会<br>*<br> <br> 超级纯粹的一个模块,实现out of memory killer.当内存严重不足的时候选择<br>一个"弱者",同过强制信号kill掉,释放出内存。<br> 提供了两个借口:<br> void oom_kill(void)<br> int out_of_memory(void)<br> 并且只有一个地方使用,vmscan.c:<br>int kswapd(void *unused)<br>{<br> ........<br> else if (out_of_memory()) {<br> oom_kill();<br> }<br> <br>}<br> 分析filemap.c的时候,了解过kswapd的作用,罗列一下:<br>*****kswapd (mm/vmscan.c)<br> +---->do_try_to_free_pages (如果内存已经不够用)<br> +-->page_launder<br> | +-->扫描 <inactive_dirty_list><br> | +-->对dirty页启动回写(包括mapping和buffer cache)<br> +-->refill_inactive<br> +-->refill_inactive_scan <br> +-->扫描<active_list>,选择合适页面移入<br> <inactive_dirty_list><br> +-->swap_out,对进程启动页面换出<br> +-->try_to_swap_out将选中页面放入<br> <inactive_dirty_list><br> +----->refill_inactive_scan<br> <br> <br> 先来看看什么叫做内存严重不足:<br>int out_of_memory(void)<br>{<br> struct sysinfo swp_info;<br><br> /* Enough free memory? Not OOM. */<br> if (nr_free_pages() > freepages.min)//每个node,每个zone的buddy系统页面余量不足<br> return 0;<br><br> if (nr_free_pages() + nr_inactive_clean_pages() > freepages.low)//即使算上可以立即<br> return 0; //回收的页面,也少的可怜<br><br> /* Enough swap space left? Not OOM. */<br> si_swapinfo(&swp_info);<br> if (swp_info.freeswap > 0)//连磁盘上的空间都不够用了<br> return 0;<br><br> /* Else... */<br> return 1; //请找个替死鬼吧<br>}<br><br> 然后就是选择哪个进程的问题了:<br>void oom_kill(void)<br>{<br> //选择一个进程<br> struct task_struct *p = select_bad_process();<br><br> ...<br> //授予选中的进程很高的优先级,让他尽快结束运行<br> p->counter = 5 * HZ;<br> p->flags |= PF_MEMALLOC;<br><br> /* This process has hardware access, be more careful. */<br> //强制发送信号,结束其运行<br> if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO)) {<br> force_sig(SIGTERM, p);<br> } else {<br> force_sig(SIGKILL, p);<br> }<br><br> /*<br> * Make kswapd go out of the way, so "p" has a good chance of<br> * killing itself before someone else gets the chance to ask<br> * for more memory.<br> */<br> //只有kswapd调用此函数,所以,这就是让kswapd让出cpu<br> //重新调度的时候,被选中的进程可可能尽快结束运行,释放资源<br> current->policy |= SCHED_YIELD;<br> schedule();<br> return;<br>}<br> <br> kswapd(oom_kill)选中要kill的进程,发送一个信号给这个进程,然后kswapd让<br>出cpu,是选中的进程可以得到调度.当选中的进程开始运行的时候,因为有一个信号<br>处于peding状态,所以系统建立一个运行signal的环境,并开始处理信号.最后被选<br>中的进程退出运行,释放资源.至于更详细的过程等到分析信号的时候再议.<br> <br> select_bad_process选择badness值最高的进程,我们来看看什么样的进程最有<br>可能为系统牺牲:<br>static int badness(struct task_struct *p)<br>{<br> int points, cpu_time, run_time;<br><br> if (!p->mm)<br> return 0;<br> /*<br> * The memory size of the process is the basis for the badness.<br> */<br> points = p->mm->total_vm; //占有内存越多,越可能被干掉<br><br> /*<br> * CPU time is in seconds and run time is in minutes. There is no<br> * particular reason for this other than that it turned out to work<br> * very well in practice. This is not safe against jiffie wraps<br> * but we don't care _that_ much...<br> */<br> cpu_time = (p->times.tms_utime + p->times.tms_stime) >> (SHIFT_HZ + 3);<br> run_time = (jiffies - p->start_time) >> (SHIFT_HZ + 10);<br><br> points /= int_sqrt(cpu_time);//占有cpu越多,即越忙,就越有可能生存<br> points /= int_sqrt(int_sqrt(run_time));//运行时间越久越有生存机会<br><br> /*<br> * Niced processes are most likely less important, so double<br> * their badness points.<br> */<br> if (p->nice > 0)<br> points *= 2;//越谦让就死的越快(不要说不公平啊)<br><br> /*<br> * Superuser processes are usually more important, so we make it<br> * less likely that we kill those.<br> */<br> //管理员的程序需要尽力保留下来<br> if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||<br> p->uid == 0 || p->euid == 0)<br> points /= 4; <br><br> /*<br> * We don't want to kill a process with direct hardware access.<br> * Not only could that mess up the hardware, but usually users<br> * tend to only have this flag set on applications they think<br> * of as important.<br> */<br> //那些直接操作硬件的程序可以获取更多生存机会<br> if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))<br> points /= 4;<br>#ifdef DEBUG<br> printk(KERN_DEBUG "OOMkill: task %d (%s) got %d points\n",<br> p->pid, p->comm, points);<br>#endif<br> return points;<br>}<br> <br><br></pre>
</td>
</tr>
</tbody>
</table></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -