<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>Rest Valley &#187; memory</title> <atom:link href="http://lihdd.net/tag/memory/feed/" rel="self" type="application/rss+xml" /><link>http://lihdd.net</link> <description>The scratchpad of quark</description> <lastBuildDate>Sat, 09 Oct 2010 13:56:19 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=</generator> <item><title>Limited Memory</title><link>http://lihdd.net/limited-memory/</link> <comments>http://lihdd.net/limited-memory/#comments</comments> <pubDate>Wed, 28 Oct 2009 07:04:23 +0000</pubDate> <dc:creator>quark</dc:creator> <category><![CDATA[Coding]]></category> <category><![CDATA[archlinux]]></category> <category><![CDATA[c]]></category> <category><![CDATA[memory]]></category><guid
isPermaLink="false">http://lihdd.net/?p=235</guid> <description><![CDATA[今天在虚拟机里面用Word处理文档的时候，突然硬盘灯一阵狂闪，然后虚拟机就一起消失了。 这种事情屡见不鲜，很明显是Linux内核把占用最多内存的程序（这次是VirtualBox）终止掉了，而硬盘灯为什么会狂闪呢？这是因为在内存用光之前，Linux的pdflush会把dirty pages写回磁盘上腾出内存给其他程序用。这段时间系统几乎处于不可用状态，Annoying! oom_killer 默认配置下，当没有内存可以用而又要用到内存时，Linux内核的oom_killer（out of memory killer）会扫描一遍占用内存最多的程序（可能有多个，比如VirtualBox和Firefox一起悲剧），并把它们结束掉。 这种扫描其实代价还是挺大的，可以选择让oom_killer不要扫描出用内存最多的进程，只是解决掉申请内存的那些进程： sysctl -w vm.oom_kill_allocating_task = 1 使用这样的设置，oom_killer不会去花时间寻找占内存最多的进程杀掉，VirtualBox和Firefox就有一定机会幸免。但是在内存用完的那一瞬间，谁去申请或者使用一片空白的内存，谁就会悲剧，而且可能是几个进程一起被杀掉，充满了不可预测性（比如，Xorg被杀掉，于是许多程序连带就挂掉了，再比如后台的mysqld被杀掉也会带来许多不方便），而且也没有避免pdflush在最后关头让硬盘灯狂闪的情况。 总之，oom_killer很不和谐，最好不要让它出场。在这一点上，openSolaris似乎做的就比较好，从外表上看，在内存不够的时候，系统不会去主动杀掉正在运行的程序，而是拒绝运行新的程序，并且运行中的程序如果申请内存的话就会被暂停，直至有内存可以给它的时候才继续运行。 overcommit 那么系统为什么不能提前检测到内存用完呢，malloc是有可能返回NULL的啊？现在的操作系统中，允许过分地申请内存，如果只是申请内存而没有实际使用的话，可以申请到比实际内存大许多的空间（比如用malloc申请内存，while(1) malloc(x);这样的程序都可以运行好长时间），只有一旦开始用（比如用memset去填），才会计入真正的内存使用，这时候如果内存真的不够了，那么oom_killer就上场了。 目前的Linux提供了一些选项用来调整这种内存策略 :-) 默认情况下，vm.overcommit_memory = 0，这时候可以申请到比较多的内存，但是仍然会在一定的时候申请失败。 还有更宽松一些的，如果 vm.overcommit_memory = 1，所有的malloc都会无条件成功 相当可怕的世界。 最后一种选择就是这个了： sysctl -w vm.overcommit_memory = 2 这时候，对申请内存总数有严格的限制，malloc会在超过限制的时候返回NULL，应用程序可以适当处理这种情况，而oom_killer再也不会蹦出来了，pdflush也不会让硬盘转得系统没响应，如果一个程序不能适当处理这种情况，就立即挂掉，干净利落。 但是这也有坏处，这时候参数vm.overcommit_ratio也会起作用，默认是50，意思是只能分配到实际物理内存的50%。如果没有交换区的话，overcommit_ratio设置得小就会很悲剧，几乎什么都做不了。 那把它设置成100，事情就非常和谐了？没有这样简单，这里的限制是申请内存总数的限制，如果申请了却没有实际用到的话，也是计入总数的。这样的话，实际内存没有用完，程序也很有可能申请不到内存，有一些内存就被浪费了。 虽然overcommit_ratio可以被设置成大于100的数，但是到底设置成多少确是个棘手的问题，设置大了，就和没有限制一样，内存用完时硬盘会狂转，系统会失去响应一段时间，oom_killer有可能会上场，设置小了，有可能几百兆的内存被白白浪费了 检查内存信息可以看到： % cat /proc/meminfo MemTotal: 2064616 kB MemFree: 1556672 kB .... CommitLimit: 2064616 kB Committed_AS: 769068 [...]]]></description> <content:encoded><![CDATA[<p>今天在虚拟机里面用Word处理文档的时候，突然硬盘灯一阵狂闪，然后虚拟机就一起消失了。</p><p>这种事情屡见不鲜，很明显是Linux内核把占用最多内存的程序（这次是VirtualBox）终止掉了，而硬盘灯为什么会狂闪呢？这是因为在内存用光之前，Linux的pdflush会把dirty pages写回磁盘上腾出内存给其他程序用。这段时间系统几乎处于不可用状态，Annoying! <img
src='http://lihdd.net/wp-includes/images/smilies/icon_evil.gif' alt=':evil:' class='wp-smiley' /> <span
id="more-235"></span></p><h3>oom_killer</h3><p>默认配置下，当没有内存可以用而又要用到内存时，Linux内核的oom_killer（out of memory killer）会扫描一遍占用内存最多的程序（可能有多个，比如VirtualBox和Firefox一起悲剧），并把它们结束掉。</p><p>这种扫描其实代价还是挺大的，可以选择让oom_killer不要扫描出用内存最多的进程，只是解决掉申请内存的那些进程：</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">sysctl <span style="color: #660033;">-w</span> vm.oom_kill_allocating_task = <span style="color: #000000;">1</span></pre></div></div><p>使用这样的设置，oom_killer不会去花时间寻找占内存最多的进程杀掉，VirtualBox和Firefox就有一定机会幸免。但是在内存用完的那一瞬间，谁去申请或者使用一片空白的内存，谁就会悲剧，而且可能是几个进程一起被杀掉，充满了不可预测性（比如，Xorg被杀掉，于是许多程序连带就挂掉了，再比如后台的mysqld被杀掉也会带来许多不方便），而且也没有避免pdflush在最后关头让硬盘灯狂闪的情况。</p><p>总之，oom_killer很不和谐，最好不要让它出场。在这一点上，openSolaris似乎做的就比较好，从外表上看，在内存不够的时候，系统不会去主动杀掉正在运行的程序，而是拒绝运行新的程序，并且运行中的程序如果申请内存的话就会被暂停，直至有内存可以给它的时候才继续运行。</p><h3>overcommit</h3><p>那么系统为什么不能提前检测到内存用完呢，malloc是有可能返回NULL的啊？现在的操作系统中，允许过分地申请内存，如果只是申请内存而没有实际使用的话，可以申请到比实际内存大许多的空间（比如用malloc申请内存，<code>while(1) malloc(x);</code>这样的程序都可以运行好长时间），只有一旦开始用（比如用memset去填），才会计入真正的内存使用，这时候如果内存真的不够了，那么oom_killer就上场了。</p><p>目前的Linux提供了一些选项用来调整这种内存策略 :-)</p><p>默认情况下，<code>vm.overcommit_memory = 0</code>，这时候可以申请到比较多的内存，但是仍然会在一定的时候申请失败。</p><p>还有更宽松一些的，如果 <code>vm.overcommit_memory = 1</code>，所有的malloc都会无条件成功 <img
src='http://lihdd.net/wp-includes/images/smilies/icon_eek.gif' alt='8-O' class='wp-smiley' /> 相当可怕的世界。</p><p>最后一种选择就是这个了：</p><div
class="wp_syntax"><div
class="code"><pre class="bash" style="font-family:monospace;">sysctl <span style="color: #660033;">-w</span> vm.overcommit_memory = <span style="color: #000000;">2</span></pre></div></div><p>这时候，对申请内存总数有严格的限制，malloc会在超过限制的时候返回NULL，应用程序可以适当处理这种情况，而oom_killer再也不会蹦出来了，pdflush也不会让硬盘转得系统没响应，如果一个程序不能适当处理这种情况，就立即挂掉，干净利落。</p><p>但是这也有坏处，这时候参数<code>vm.overcommit_ratio</code>也会起作用，默认是50，意思是只能分配到实际物理内存的50%。如果没有交换区的话，<code>overcommit_ratio</code>设置得小就会很悲剧，几乎什么都做不了。</p><p>那把它设置成100，事情就非常和谐了？没有这样简单，这里的限制是申请内存总数的限制，如果申请了却没有实际用到的话，也是计入总数的。这样的话，实际内存没有用完，程序也很有可能申请不到内存，有一些内存就被浪费了。</p><p>虽然<code>overcommit_ratio</code>可以被设置成大于100的数，但是到底设置成多少确是个棘手的问题，设置大了，就和没有限制一样，内存用完时硬盘会狂转，系统会失去响应一段时间，oom_killer有可能会上场，设置小了，有可能几百兆的内存被白白浪费了 <img
src='http://lihdd.net/wp-includes/images/smilies/icon_neutral.gif' alt=':-|' class='wp-smiley' /></p><hr
style="border: 1px solid #cccccc; height: 1px; width: 85%; color: #ffffff;" size="1" noshade="noshade" /><p>检查内存信息可以看到：</p><pre>% cat /proc/meminfo
MemTotal:        2064616 kB
MemFree:         1556672 kB
....
CommitLimit:     2064616 kB
Committed_AS:     769068 kB
....</pre><p>其中Committed_AS是程序申请的内存总和，不能超过CommitLimit。很明显地看到Committed_AS+MemFree比MemTotal大，看起来把CommitLimit设置成Committed_AS+MemFree比较合适。</p><p>不过这个时候，CommitLimit是只受<code>overcommit_ratio</code>影响的，内存使用状态在动态变化，只好写一个程序来动态修改<code>overcommit_ratio</code>了。</p><p>最后我写了这样的一段C的小程序，每一秒设置一次<code>overcommit_ratio</code>。在目前版本的Linux内核(2.6.31)上i686平台可用：</p><div
class="wp_syntax"><div
class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define _GNU_SOURCE 1</span>
&nbsp;
<span style="color: #339933;">#include &lt;unistd .h&gt;</span>
<span style="color: #339933;">#include &lt;stdio .h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib .h&gt;</span>
<span style="color: #339933;">#include &lt;err .h&gt;</span>
<span style="color: #339933;">#include &lt;errno .h&gt;</span>
<span style="color: #339933;">#include &lt;string .h&gt;</span>
&nbsp;
<span style="color: #339933;">#define errexit(status, info) fprintf(stderr, &quot;%s: %s\n&quot;, program_invocation_name, info), exit(status);</span>
&nbsp;
FILE <span style="color: #339933;">*</span>fp_meminfo<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">void</span> set_overcommitted_limit<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> value<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">char</span> new_value<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">32</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> old_len <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
	FILE <span style="color: #339933;">*</span>fp_overcommit_ratio<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>fp_overcommit_ratio <span style="color: #339933;">=</span> fopen<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/proc/sys/vm/overcommit_ratio&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;w&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		err<span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #0000dd;">4</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;can't write /proc/sys/vm/overcommit_ratio&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	fprintf<span style="color: #009900;">&#40;</span>fp_overcommit_ratio<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%d&quot;</span><span style="color: #339933;">,</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	fclose<span style="color: #009900;">&#40;</span>fp_overcommit_ratio<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #993333;">const</span><span style="color: #339933;">*</span> argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">char</span> item_name<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">32</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> item_value<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #993333;">int</span> mem_free<span style="color: #339933;">,</span> mem_total<span style="color: #339933;">,</span> committed_as<span style="color: #339933;">,</span> buffers<span style="color: #339933;">,</span> cached<span style="color: #339933;">,</span> item_count<span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #993333;">char</span> essential_names<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">32</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #ff0000;">&quot;MemTotal&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;MemFree&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Committed_AS&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Cached&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> essential_values<span style="color: #009900;">&#91;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_names<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_names<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">;;</span>sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>fp_meminfo <span style="color: #339933;">=</span> fopen<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/proc/meminfo&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;r&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
			err<span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #0000dd;">2</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;can't read /proc/meminfo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>memset<span style="color: #009900;">&#40;</span>essential_values<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
				item_count <span style="color: #339933;">=</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				item_count<span style="color: #339933;">;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
			<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>feof<span style="color: #009900;">&#40;</span>fp_meminfo<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> errexit<span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span><span style="color: #0000dd;">3</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;can't read all essential information&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			fscanf<span style="color: #009900;">&#40;</span>fp_meminfo<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot; %31[^:]%*[^ ]%d%*[^<span style="color: #000099; font-weight: bold;">\n</span>]&quot;</span><span style="color: #339933;">,</span> item_name<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>item_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&amp;&amp;</span> 
					strcmp<span style="color: #009900;">&#40;</span>essential_names<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> item_name<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
					essential_values<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> item_value<span style="color: #339933;">;</span>
					<span style="color: #339933;">--</span>item_count<span style="color: #339933;">;</span>
					<span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		set_overcommitted_limit<span style="color: #009900;">&#40;</span>
			<span style="color: #009900;">&#40;</span>essential_values<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> essential_values<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> essential_values<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">/</span> <span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">*</span> <span style="color: #0000dd;">100</span> <span style="color: #339933;">/</span> essential_values<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		fclose<span style="color: #009900;">&#40;</span>fp_meminfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div><p>这段程序需要管理员权限运行，把它设置成开机必执行工具之一，同时在<code>/etc/sysctl.conf</code>上加上相关设置，就十分和谐啦 <img
src='http://lihdd.net/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /></p><p>就这一方面，可能还是openSolaris的做法最和谐，不过仅仅这一点并不能让我投奔openSolaris，把它作为日常使用的系统。默默地期待openSolaris和Linux都越来越好吧～</string></errno></err></stdlib></stdio></unistd></pre> ]]></content:encoded> <wfw:commentRss>http://lihdd.net/limited-memory/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced

Served from: lihdd.net @ 2012-05-19 14:49:27 -->
