<?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>Oasis Feng &#187; Misc</title>
	<atom:link href="http://blog.oasisfeng.com/category/misc/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.oasisfeng.com</link>
	<description>Challenge your imagination!</description>
	<lastBuildDate>Tue, 13 Jul 2010 16:56:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>解决Cisco AnyConnect VPN客户端的DNS优先级问题</title>
		<link>http://blog.oasisfeng.com/2010/05/25/solve-the-dns-priority-issue-in-cisco-anyconnect-vpn-client/</link>
		<comments>http://blog.oasisfeng.com/2010/05/25/solve-the-dns-priority-issue-in-cisco-anyconnect-vpn-client/#comments</comments>
		<pubDate>Mon, 24 May 2010 16:35:59 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[AnyConnect]]></category>
		<category><![CDATA[BAT]]></category>
		<category><![CDATA[Cisco]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[VPN]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/?p=900</guid>
		<description><![CDATA[Cisco AnyConnect VPN的客户端是一个工作于并行隧道（Split Tunnel）模式下的VPN软件，它可以方便的同时使用内外网两不误。它通过连接VPN后动态激活平时禁用的VPN虚拟网络适配器，并根据远端网关的配置应用相应的DNS和路由配置，实现了与默认网络环境无缝并行。但正是在其上述设计中的一个理想假设，为“中国特色”的互联网环境下使用它埋下了一个隐藏很深的问题。 如果你所连接的VPN网络本身是与Internet连通的，而且DNS也可解析外网的网址，由于AnyConnect会将VPN网络适配器的优先级提升到最高，因此远端的DNS配置会取代本地网络（例如家里的宽带网络）。如果你的本地网络和远程网络是同一接入线路，倒还感觉不到这之中的差别。但如果其中一个是电信线路，另一个是联通（网通）线路，你就会遇到一个很悲惨的状况：本地网络访问国内主要网站的速度会显著降低，因为DNS对大型网站CDN的解析结果是和你现有路由完全不同的线路，想象一下在你的联通（网通）宽带下访问电信线路的网站，那种感觉…… 为了解决这个问题，我先后尝试了在注册表里静态调整适配器优先级、修改VPN适配器DNS配置等多种办法，但AnyConnect在每次连接时强制重置适配器配置和优先级的极端手段让我的大部分努力都付之东流。要不是公司网络只支持它家的VPN客户端，我真不想再看到这样一个流氓软件…… 不得己，只好祭出最后的杀手锏，用批处理写了一个动态监视和修正DNS配置的脚本，放到任务计划中去自动执行。（眼看我的任务计划中已经塞了越来越多这类fix脚本，也只能留下一声叹息了……）废话不多说，直接上脚本： anyconnect_vpn_dns_fix.bat @echo off set dns=127.0.0.1 :loop netsh interface ip show dnsservers name="Cisco AnyConnect VPN Client Connection" &#124; find "Cisco" &#62; nul if errorlevel 1 goto sleep netsh interface ip show dnsservers name="Cisco AnyConnect VPN Client Connection" &#124; find "%dns%" &#62; nul if errorlevel 1 goto fix goto sleep [...]]]></description>
			<content:encoded><![CDATA[<p>Cisco AnyConnect VPN的客户端是一个工作于并行隧道（Split Tunnel）模式下的VPN软件，它可以方便的同时使用内外网两不误。它通过连接VPN后动态激活平时禁用的VPN虚拟网络适配器，并根据远端网关的配置应用相应的DNS和路由配置，实现了与默认网络环境无缝并行。但正是在其上述设计中的一个理想假设，为“中国特色”的互联网环境下使用它埋下了一个隐藏很深的问题。</p>
<p>如果你所连接的VPN网络本身是与Internet连通的，而且DNS也可解析外网的网址，由于AnyConnect会将VPN网络适配器的优先级提升到最高，因此远端的DNS配置会取代本地网络（例如家里的宽带网络）。如果你的本地网络和远程网络是同一接入线路，倒还感觉不到这之中的差别。但如果其中一个是电信线路，另一个是联通（网通）线路，你就会遇到一个很悲惨的状况：本地网络访问国内主要网站的速度会显著降低，因为DNS对大型网站CDN的解析结果是和你现有路由完全不同的线路，想象一下在你的联通（网通）宽带下访问电信线路的网站，那种感觉……</p>
<p><span id="more-900"></span>为了解决这个问题，我先后尝试了在注册表里静态调整适配器优先级、修改VPN适配器DNS配置等多种办法，但AnyConnect在每次连接时强制重置适配器配置和优先级的极端手段让我的大部分努力都付之东流。要不是公司网络只支持它家的VPN客户端，我真不想再看到这样一个流氓软件……</p>
<p>不得己，只好祭出最后的杀手锏，用批处理写了一个动态监视和修正DNS配置的脚本，放到任务计划中去自动执行。（眼看我的任务计划中已经塞了越来越多这类fix脚本，也只能留下一声叹息了……）废话不多说，直接上脚本：</p>
<p>anyconnect_vpn_dns_fix.bat</p>
<pre>@echo off
set dns=127.0.0.1
:loop
netsh interface ip show dnsservers name="Cisco AnyConnect VPN Client Connection" | find "Cisco" &gt; nul
if errorlevel 1 goto sleep

netsh interface ip show dnsservers name="Cisco AnyConnect VPN Client Connection" | find "%dns%" &gt; nul
if errorlevel 1 goto fix

goto sleep

:fix
echo New Cisco AnyConnect VPN connection detected, apply the DNS fix...
netsh interface ip add dnsservers name="Cisco AnyConnect VPN Client Connection" address=%dns% index=1 validate=yes
goto sleep

:sleep
rem Sleep 10 seconds
ping -n 10 127.0.0.1 &gt; nul
goto loop</pre>
<p>在将这个脚本丢进任务计划之前，还有几点需要补充说明：</p>
<ul>
<li>请将第二行的“127.0.0.1”改为你实际的宽带DNS服务器地址，比如路由器地址。</li>
<li>这个脚本需要提升的UAC权限，因此务必在计划任务中设置“使用最高权限运行”</li>
<li>为了消除丑陋的命令提示符窗口，建议使用<a href="http://www.ntwind.com/software/utilities/hstart.html">hstart.exe</a>来启动它，用“/wait /noconsole”参数</li>
</ul>
<p>用了这个脚本后，你可能会面临一个新的问题——VPN所连网域的内部域名无法正常解析了，而是跳到ISP的“网址智能纠错”页面中去了。这其实并不是上述脚本本身的问题，因为主DNS（即宽带DNS）无法解析的域名，本应传递给次DNS（VPN DNS），但却不幸遭遇了又一个典型“中国特色”互联网的变态产物——DNS劫持。对于这个问题的解决之道，请关注我的下一篇Blog：《中国特色互联网的生存法则——DNS免疫篇》</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2010/05/25/solve-the-dns-priority-issue-in-cisco-anyconnect-vpn-client/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google Buzz的解读误区</title>
		<link>http://blog.oasisfeng.com/2010/02/11/misunderstandings-about-google-buzz/</link>
		<comments>http://blog.oasisfeng.com/2010/02/11/misunderstandings-about-google-buzz/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 15:40:24 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Buzz]]></category>
		<category><![CDATA[FriendFeed]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Salmon]]></category>
		<category><![CDATA[Social]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/?p=863</guid>
		<description><![CDATA[Google发布Buzz后，网络上迅速出现了大量对Buzz的评论，有正面的，有负面的，有炒作概念的，有跟着起哄的，甚至引发了大家对Gmail安全的担忧。这其中不乏一些对Buzz的误读，所以，在这里以我个人的理解来解释一下。 “Google Buzz是Twitter杀手！” 这是大多数媒体最喜欢的炒作方式，又一个Killer App出现了，于是编辑们都兴奋了，又可以赚足眼球了。事实上，Google Buzz和Twitter总体来看并不是一个层面上的应用，还构不成真正意义上的Killer。一些冷静的分析还是看的比较清楚，Google Buzz其实主要针对的是FriendFeed，因为它们都是聚合平台，让不同源头的信息聚合在一起。Buzz相对于FriendFeed的最大进步在于，它除了聚合信息之外，还创造性的利用Social Graph来聚合人际关系。 当然，Google Buzz除了聚合功能外，自身也充当了一个简单的信息源，可以在Buzz上发表富媒体信息。但事实上，你有自己充分的选择权，完全可以保持原有的习惯，在WordPress上写Blog，在Twitter上唠叨几句，这些信息最终都会自动被汇总到Buzz中来。 “我们不需要又一个社交网络” 当你迫不及待的跑来Buzz上兴奋的吼了几句后，才意识到它和Twitter也没多少差，反而在这里找不到Twitter上那种“振臂一呼，Follower百应”的成就感了。没过多久，你就会逐渐淡忘掉Buzz。这是因为，你把Buzz当成了一个和Twitter、Facebook、MySpace一样的社交网络。“又一个新的SNS，我不得不又一次花费时间从头建立我的关系网络。”其实这不奇怪，不光是你，连Microsoft也这么认为。 本质上，Buzz并不想打造一个新的社交网络，恰恰相反，它的目的是推进一系列开放标准，使用户不必在各个SNS维护一个又一个彼此独立的关系网络，使人际关系得以重用和汇聚，进而构造起一个去中心化的Social Graph，不依附于某一个特定的SNS。 Buzz倡导运用XHTML Friends Network (XFN) 和 Friend of a Friend (FOAF) 挖掘和汇聚用户既有的关系网，实现SNS间的互操作性。如果各个开放SNS都能响应这一号召的话，那么将来我们就再也不用担心自己的人际关系被锁死在某个SNS中，甚至还可以借助新的SNS发现原有SNS中漏掉的好友。 “Buzz让信息的回复和评论更加破碎了” 这一点确实是目前不争的事实，因为无论你从Twitter往Buzz同步也好，还是打算反过来从Buzz发布到Twitter，你都得面对一个问题，回复和评论的不同步。你很可能因为只在Twitter上读消息而遗漏了Buzz里别人的评论，或许在习惯了Buzz后，又冷落了Twitter上的Followers。在Web应用越来越多的引入“聚合（Aggregation）”功能后，这个问题逐渐凸显出来。Google Buzz现在没有解决这个问题，但这只是因为目前的Buzz还尚不完整。Buzz的API文档中有一节“Coming Soon”，其中提到了Buzz未来对这一问题的解决之道——Salmon。 之所以现在没有推出Salmon支持，我猜想，一方面是由于这个规范尚处在Draft阶段，另一方面它无法从Google单方面实现，因为信息源和聚合者都必须遵从Salmon协议，才能完整的实现评论同步。这个事情倘若让任何一家其它互联网公司来推，可能都收效甚微，但由Google Buzz倡导，其影响力就不可同日而语了。因此，Google在完成Salmon的支持前，先放出Roadmap来，让大家都意识到Google开放的心态和坚定的决心，这样Salmon才有机会得到广泛的认可和支持。 所以，就如同Wave对大多数人来说也不过尔尔，只有当你透过API去洞察其背后所希望表达的真正意图后，才能深刻理解Google每一款产品的前瞻和愿景。在大多数人被Buzz的优雅与便捷所打动时，我更看重的是它将对整个SNS生态圈所产生的深远影响，和它在推动开放和标准化上的显著贡献。]]></description>
			<content:encoded><![CDATA[<p>Google发布Buzz后，网络上迅速出现了大量对Buzz的评论，有正面的，有负面的，有炒作概念的，有跟着起哄的，甚至引发了大家对Gmail安全的担忧。这其中不乏一些对Buzz的误读，所以，在这里以我个人的理解来解释一下。</p>
<p><strong>“Google Buzz是Twitter杀手！”</strong></p>
<p>这是大多数媒体最喜欢的炒作方式，又一个Killer App出现了，于是编辑们都兴奋了，又可以赚足眼球了。事实上，Google Buzz和Twitter总体来看并不是一个层面上的应用，还构不成真正意义上的Killer。一些冷静的分析还是看的比较清楚，Google Buzz其实主要针对的是<a href="http://friendfeed.com/">FriendFeed</a>，因为它们都是聚合平台，让不同源头的信息聚合在一起。Buzz相对于FriendFeed的最大进步在于，它除了聚合信息之外，还创造性的利用<a href="http://code.google.com/apis/socialgraph/">Social Graph</a>来聚合人际关系。</p>
<p>当然，Google Buzz除了聚合功能外，自身也充当了一个简单的信息源，可以在Buzz上发表富媒体信息。但事实上，你有自己充分的选择权，完全可以保持原有的习惯，在WordPress上写Blog，在Twitter上唠叨几句，这些信息最终都会自动被汇总到Buzz中来。</p>
<p><strong>“我们不需要又一个社交网络”</strong></p>
<p>当你迫不及待的跑来Buzz上兴奋的吼了几句后，才意识到它和Twitter也没多少差，反而在这里找不到Twitter上那种“振臂一呼，Follower百应”的成就感了。没过多久，你就会逐渐淡忘掉Buzz。这是因为，你把Buzz当成了一个和Twitter、Facebook、MySpace一样的社交网络。<a href="http://code.google.com/apis/socialgraph/">“又一个新的SNS，我不得不又一次花费时间从头建立我的关系网络。”</a>其实这不奇怪，不光是你，连<a href="http://techcrunch.com/2010/02/09/microsoft-slams-google-buzz/">Microsoft也这么认为</a>。</p>
<p>本质上，Buzz并不想打造一个新的社交网络，恰恰相反，它的目的是推进一系列开放标准，使用户不必在各个SNS维护一个又一个彼此独立的关系网络，使人际关系得以重用和汇聚，进而构造起一个去中心化的Social Graph，不依附于某一个特定的SNS。</p>
<p>Buzz倡导运用<a href="http://gmpg.org/xfn/">XHTML Friends Network</a> (XFN) 和 <a href="http://www.foaf-project.org/">Friend of a Friend</a> (FOAF) 挖掘和汇聚用户既有的关系网，实现SNS间的互操作性。如果各个开放SNS都能响应这一号召的话，那么将来我们就再也不用担心自己的人际关系被锁死在某个SNS中，甚至还可以借助新的SNS发现原有SNS中漏掉的好友。</p>
<p><strong>“Buzz让信息的回复和评论更加破碎了”</strong></p>
<p>这一点确实是目前不争的事实，因为无论你从Twitter往Buzz同步也好，还是打算反过来从Buzz发布到Twitter，你都得面对一个问题，回复和评论的不同步。你很可能因为只在Twitter上读消息而遗漏了Buzz里别人的评论，或许在习惯了Buzz后，又冷落了Twitter上的Followers。在Web应用越来越多的引入“聚合（Aggregation）”功能后，这个问题逐渐凸显出来。Google Buzz现在没有解决这个问题，但这只是因为目前的Buzz还尚不完整。<a href="http://code.google.com/apis/buzz/documentation/#coming-soon">Buzz的API文档中有一节“Coming Soon”</a>，其中提到了Buzz未来对这一问题的解决之道——<a href="http://www.salmon-protocol.org/">Salmon</a>。</p>
<p>之所以现在没有推出Salmon支持，我猜想，一方面是由于这个规范尚处在Draft阶段，另一方面它无法从Google单方面实现，因为信息源和聚合者都必须遵从Salmon协议，才能完整的实现评论同步。这个事情倘若让任何一家其它互联网公司来推，可能都收效甚微，但由Google Buzz倡导，其影响力就不可同日而语了。因此，Google在完成Salmon的支持前，先放出Roadmap来，让大家都意识到Google开放的心态和坚定的决心，这样Salmon才有机会得到广泛的认可和支持。</p>
<p>所以，就如同<a href="http://blog.oasisfeng.com/2009/10/12/the-strategy-vision-behind-google-wave/">Wave对大多数人来说也不过尔尔</a>，只有当你透过API去洞察其背后所希望表达的真正意图后，才能深刻理解Google每一款产品的前瞻和愿景。在大多数人被Buzz的优雅与便捷所打动时，我更看重的是它将对整个SNS生态圈所产生的深远影响，和它在推动开放和标准化上的显著贡献。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2010/02/11/misunderstandings-about-google-buzz/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[好消息] 动感地带的网外短信终于可以计入套餐内免费短信数了！</title>
		<link>http://blog.oasisfeng.com/2009/01/08/cross-network-sms-of-mzone-is-now-accounted-within-monthly-free-sms/</link>
		<comments>http://blog.oasisfeng.com/2009/01/08/cross-network-sms-of-mzone-is-now-accounted-within-monthly-free-sms/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 13:33:20 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/?p=584</guid>
		<description><![CDATA[以前发往联通、电信小灵通的短信不仅不能计入套餐内的免费短信，而且还收取比移动网内普通短信更高的费用。 从今年元旦起，工信部要求各运营商统一网内外短信资费，因此移动用户往国内任何手机或小灵通发送短信的费用都统一为0.1元。那么更让人关注的是，动感地带的套餐内免费短信是否也包含网外短信呢？就这一点，中国移动给出了一个很模糊的回答——请参见各套餐的说明…… 去移动网站上查了一下，各套餐的资费说明均已更新，至少我目前所用的动感地带套餐已经将网外短信纳入套餐内的400条免费短信了，以后就可以毫无顾忌的随时给家人的小灵通发短信咯！ 话说这400条也不是那么容易用完的……]]></description>
			<content:encoded><![CDATA[<p>以前发往联通、电信小灵通的短信不仅不能计入套餐内的免费短信，而且还收取比移动网内普通短信更高的费用。</p>
<p>从今年元旦起，工信部要求各运营商统一网内外短信资费，因此移动用户往国内任何手机或小灵通发送短信的费用都统一为0.1元。那么更让人关注的是，动感地带的套餐内免费短信是否也包含网外短信呢？就这一点，中国移动给出了一个很模糊的回答——请参见各套餐的说明……</p>
<p>去移动网站上查了一下，各套餐的资费说明均已更新，至少我目前所用的动感地带套餐已经将网外短信纳入套餐内的400条免费短信了，以后就可以毫无顾忌的随时给家人的小灵通发短信咯！</p>
<p>话说这400条也不是那么容易用完的……</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2009/01/08/cross-network-sms-of-mzone-is-now-accounted-within-monthly-free-sms/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>在Windows 2008下安装RamDisk</title>
		<link>http://blog.oasisfeng.com/2009/01/05/install-ramdisk-on-windows-server-2008/</link>
		<comments>http://blog.oasisfeng.com/2009/01/05/install-ramdisk-on-windows-server-2008/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 17:24:14 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[64bit]]></category>
		<category><![CDATA[gavotte]]></category>
		<category><![CDATA[RamDisk]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Windows2008]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/?p=566</guid>
		<description><![CDATA[去年新买的PC配置了4G内存，虽然64bit的Windows Server 2008可以完整的访问到全部内存空间，但事实上大部分时候，仍然有相当容量的内存是处于闲置状态的，因此安装一个RamDisk来加速临时文件的存取可以更好的利用硬件资源。 RamDisk现在有很多不同的版本，虽然功能都差不多。我选择了CCF的gavotte所开发的版本，免费、小巧，而且设置很方便，不像某某收费的RamDisk，还不能调整容量。 gavotte提供了64bit的版本，但如果你想安装在Windows Server 2008下，则不得不面临一个麻烦。由于微软强制要求“关键驱动”必须通过数字签名，所以安装后RamDisk后你会发现你的Windows无法启动了，它会提示“有驱动程序未通过数字签名，Windows拒绝启动”。这时你唯一的选择只能在刚启动时按F8，选择“禁用驱动程序签名强制”，从而可以顺利的进入Windows。但是，总不能每次启动时都得盯着屏幕，抓住短暂的时机抢按F8吧…… 好在就有这么一个神奇的软件，可以帮你自动完成上述启动过程中的特殊步骤，完全不必人工干预，它就是“Ready Driver Plus”。借助它，RamDisk终于可以在Windows Server 2008下完美使用了。虽然引入了一点安全风险，但作为Power User的你，应该不用担心这一点吧？（话说XP下没强制驱动签名不也照样裸奔嘛~）]]></description>
			<content:encoded><![CDATA[<p>去年新买的PC配置了4G内存，虽然64bit的Windows Server 2008可以完整的访问到全部内存空间，但事实上大部分时候，仍然有相当容量的内存是处于闲置状态的，因此安装一个RamDisk来加速临时文件的存取可以更好的利用硬件资源。</p>
<p>RamDisk现在有很多不同的版本，虽然功能都差不多。我选择了<a target="_blank" href="https://bbs.et8.net/bbs/showthread.php?t=906641">CCF的gavotte所开发的版本</a>，免费、小巧，而且设置很方便，不像某某收费的RamDisk，还不能调整容量。</p>
<p>gavotte提供了64bit的版本，但如果你想安装在Windows Server 2008下，则不得不面临一个麻烦。由于微软强制要求“关键驱动”必须通过数字签名，所以安装后RamDisk后你会发现你的Windows无法启动了，它会提示“有驱动程序未通过数字签名，Windows拒绝启动”。这时你唯一的选择只能在刚启动时按F8，选择“禁用驱动程序签名强制”，从而可以顺利的进入Windows。但是，总不能每次启动时都得盯着屏幕，抓住短暂的时机抢按F8吧……</p>
<p>好在就有这么一个神奇的软件，可以帮你自动完成上述启动过程中的特殊步骤，完全不必人工干预，它就是<a target="_blank" href="http://citadel.x10hosting.com/readydriverplus/">“Ready Driver Plus”</a>。借助它，RamDisk终于可以在Windows Server 2008下完美使用了。虽然引入了一点安全风险，但作为Power User的你，应该不用担心这一点吧？（话说XP下没强制驱动签名不也照样裸奔嘛~）</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2009/01/05/install-ramdisk-on-windows-server-2008/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>开发人员的月光宝盒 —— 基于CPU的“时光倒流”技术畅想</title>
		<link>http://blog.oasisfeng.com/2008/07/01/cpu-based-execution-rollback/</link>
		<comments>http://blog.oasisfeng.com/2008/07/01/cpu-based-execution-rollback/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 15:27:38 +0000</pubDate>
		<dc:creator>oasisfeng</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[Debug]]></category>
		<category><![CDATA[History]]></category>
		<category><![CDATA[Rollback]]></category>

		<guid isPermaLink="false">http://blog.oasisfeng.com/?p=319</guid>
		<description><![CDATA[一. 重现罕见问题——开发人员永远的痛 但凡做过程序调试的开发人员，一定都有过面临难以重现的问题时仰天兴叹的经历，祈祷老天赐予传说中的“月光宝盒”，从而逆转时光揪出那引发程序错误的元凶！ 即使在错误跟踪技术经历长足发展的今天，哪怕是经过周密故障跟踪机制加持的代码，程序员仍然对那些难以重现的问题提心吊胆。错误跟踪机制再先进，也难以完整记录整个程序的运行轨迹和任何过去时刻的系统状态。数据覆盖的不可逆决定了程序执行的单向性，就像时间之箭，谁也不能让它转向。但时间的单向性并不意味着过去的时光不能从头来过，就像“月光宝盒”虽然不能使你回身飞上万丈绝壁，但却可以将你带回过去的某一时刻，让后面的历史重新来过。 二. 挑战时间之箭，已逝历史也能重历？ 倘若我们能完整的记录系统在某一时刻的所有状态，那么回退此后的程序执行路径是否就成为可能？一旦历史得以回放，首先，必须保证回退后的程序执行路径具有唯一确定性，否则利用这一技术定位问题的希望就成了镜花水月。影响CPU执行序列确定性的因素有哪些呢？寄存器、标志位、内存数据和IO操作（CPU的工作模式也可以看作是特殊的标志）。其中，前两者的保存可以轻松实现，而内存和IO操作就要复杂很多了。 我们知道，现代的CPU中均集成了多级的缓存（Cache），用作内存数据的暂存区。CPU指令对内存的数据写入其实都先写入了缓存中，大部分通用CPU的写缓存策略并不立即将其同步到物理内存，而是等到该数据项从缓存中排挤出后才写回到物理内存中。这种“回写（Write-back）”缓存机制正好为内存数据的回退创造了条件，后面将会详细描述我们如何对它加以利用。 最后，让我们来看看IO操作。尽管计算机中的IO操作包罗万象，涉及的器件和设备也千差万别，但最常见的IO操作离不开磁盘和输入输出设备。而后者的操作频率相对CPU的执行速度来说，实在只能算是“难得一遇”了。对于前者，磁盘的IO操作，虽然CPU本身没有能力记录其状态，但幸运的是，操作系统已经为存储设备准备好了类似于CPU内的缓存机制，不过是拿内存作为其缓存介质。于是，这个看似合情合理的设计再次为我们创造了绝好的铺垫。因为只要磁盘缓存尚未过期，从CPU的视角来看，并没有出现真正的IO操作（变成了内存读写），那么只需通过回退内存改变（包括了磁盘缓存的刷新）的改变即可间接实现磁盘IO操作的回退。事实上，由于操作系统提供的磁盘缓存通常都远大于CPU中的缓存，所以两者的缓存淘汰算法没有太大分歧的话，都不太可能出现磁盘缓存先于CPU缓存被挤出。当然，为策万全也可以让操作系统与CPU对磁盘缓存进行协同管理。 三. 铸造月光宝盒，驾驭程序的命运之轮 好了，万事俱备，就让我们来勾勒出“月光宝盒”的完整设计吧。为了表述的方便，下面均以进入“时光守护模式”的CPU为主角。 首先，我们需要设定“回退窗口”的尺寸，权且以CPU指令为单位，比如100条指令。那么CPU每执行100条指令，就产生一个硬中断，进入特殊的“快照”流程，完成下面几个步骤： （1）保存中断现场，包括全部寄存器、标志位和内部状态。 （2）将特殊寄存器——“回退计数器”的值加一，作为本次“回退点”的唯一标识。 （3）将回退点标识写入CPU缓存队列中，并可以视作普通缓存条目一样被淘汰。但它将影响该标识前后数据缓存条目的“刷新（Renew）”机制：比最新的回退点标识更旧的数据缓存条目在“刷新”时并不删除现有的条目，而是新创建一个条目记录最近的内存数据变化。这是为了保证缓存中的数据能以回退点标识为界限分阶段回退。 OK，现在CPU可以回到先前被中断的流程继续执行了。此后重复上述流程，周而复始的记录下每一个可回退时刻的快照（可以适当限定需保存的快照数上限）。 四. 重回历史轨迹，让Bug无所遁形 当CPU或者软件层的故障捕获机制遇到一个严重异常后，就该让我们的“月光宝盒”发挥奇效了！这时候，首先找出CPU缓存中所记录最早的回退点标识，以此为界，“回写（Flush）”之前的数据缓存项（这一步不是必须的）并丢弃之后的全部缓存项，然后将CPU上下文恢复到前面保存的现场（包括全部寄存器、标志位和内部状态）。 下一个瞬间，我们已然回到了这段程序在它的历史中曾经经历过的瞬间，在继续发动CPU重现历史轨迹之前，请容我们首先准备好必要的故障定位器材，比如开启单步跟踪模式、激活内存读写监视、重定向异常截获入口…… 在可以反复重历的程序轨迹前，相信即使是初出茅庐的程序员也不会再错过任何故障定位信息了。 作为后续拓展空间，我们一方面可以通过优化CPU内部的执行序列（比如结合乱序执行）进一步降低快照动作对程序执行效率的影响；另一方面可以进一步发展出无人干预的自动故障记录和恢复机制，亦或是带有执行回溯能力的“Core Dump”，提高故障定位的便利性。 五. 前路虽多阴霾，却难掩神器之光芒 作为我们力所能及范围之外的IO操作，由于它们可能破坏回退后程序执行路径的确定性，所以在目前的机制里只能以“邪恶”的反面形象出现，每次与它们的照面会使得我们此前辛苦积累起来的全部快照失去意义，不得不再从头来过，这就意味着任何回退企图都无法超越最后一次出现IO操作的时间。虽然通过为IO增设缓存通常能缓解大部分的矛盾，但IO操作的多样化和复杂性使得进一步化解困境努力显得效果甚微。 不过瑕不掩瑜，在CPU执行速度远超IO访问速度的今天，至少从概率学的角度来看，我们所面临的大部分程序执行异常都将出现在远离IO操作的时刻，使得我们仍然有较大的回退空间去捕捉问题。 六. 后记 本文纯属带点技术色彩的调侃和畅想，疏漏、谬误和欠成熟之处在所难免，也欢迎大家加入讨论！相信技术本身总是能在辩论中变得更加清晰和透彻。]]></description>
			<content:encoded><![CDATA[<p><strong>一. 重现罕见问题——开发人员永远的痛</strong></p>
<p>但凡做过程序调试的开发人员，一定都有过面临难以重现的问题时仰天兴叹的经历，祈祷老天赐予传说中的“月光宝盒”，从而逆转时光揪出那引发程序错误的元凶！</p>
<p>即使在错误跟踪技术经历长足发展的今天，哪怕是经过周密故障跟踪机制加持的代码，程序员仍然对那些难以重现的问题提心吊胆。错误跟踪机制再先进，也难以完整记录整个程序的运行轨迹和任何过去时刻的系统状态。数据覆盖的不可逆决定了程序执行的单向性，就像时间之箭，谁也不能让它转向。但时间的单向性并不意味着过去的时光不能从头来过，就像“月光宝盒”虽然不能使你回身飞上万丈绝壁，但却可以将你带回过去的某一时刻，让后面的历史重新来过。</p>
<p><strong>二. 挑战时间之箭，已逝历史也能重历？</strong></p>
<p><span id="more-319"></span>倘若我们能完整的记录系统在某一时刻的所有状态，那么回退此后的程序执行路径是否就成为可能？一旦历史得以回放，首先，必须保证回退后的程序执行路径具有唯一确定性，否则利用这一技术定位问题的希望就成了镜花水月。影响CPU执行序列确定性的因素有哪些呢？<strong>寄存器、标志位、内存数据和IO操作</strong>（CPU的工作模式也可以看作是特殊的标志）。其中，前两者的保存可以轻松实现，而内存和IO操作就要复杂很多了。</p>
<p>我们知道，现代的CPU中均集成了多级的缓存（Cache），用作内存数据的暂存区。CPU指令对内存的数据写入其实都先写入了缓存中，大部分通用CPU的写缓存策略并不立即将其同步到物理内存，而是等到该数据项从缓存中排挤出后才写回到物理内存中。这种“回写（Write-back）”缓存机制正好为内存数据的回退创造了条件，后面将会详细描述我们如何对它加以利用。</p>
<p>最后，让我们来看看IO操作。尽管计算机中的IO操作包罗万象，涉及的器件和设备也千差万别，但最常见的IO操作离不开磁盘和输入输出设备。而后者的操作频率相对CPU的执行速度来说，实在只能算是“难得一遇”了。对于前者，磁盘的IO操作，虽然CPU本身没有能力记录其状态，但幸运的是，操作系统已经为存储设备准备好了类似于CPU内的缓存机制，不过是拿内存作为其缓存介质。于是，这个看似合情合理的设计再次为我们创造了绝好的铺垫。因为只要磁盘缓存尚未过期，从CPU的视角来看，并没有出现真正的IO操作（变成了内存读写），那么只需通过回退内存改变（包括了磁盘缓存的刷新）的改变即可间接实现磁盘IO操作的回退。事实上，由于操作系统提供的磁盘缓存通常都远大于CPU中的缓存，所以两者的缓存淘汰算法没有太大分歧的话，都不太可能出现磁盘缓存先于CPU缓存被挤出。当然，为策万全也可以让操作系统与CPU对磁盘缓存进行协同管理。</p>
<p><strong>三. 铸造月光宝盒，驾驭程序的命运之轮</strong></p>
<p>好了，万事俱备，就让我们来勾勒出“月光宝盒”的完整设计吧。为了表述的方便，下面均以进入“时光守护模式”的CPU为主角。</p>
<p>首先，我们需要设定“回退窗口”的尺寸，权且以CPU指令为单位，比如100条指令。那么CPU每执行100条指令，就产生一个硬中断，进入特殊的“快照”流程，完成下面几个步骤：<br />
（1）保存中断现场，包括全部寄存器、标志位和内部状态。<br />
（2）将特殊寄存器——“回退计数器”的值加一，作为本次“回退点”的唯一标识。<br />
（3）将回退点标识写入CPU缓存队列中，并可以视作普通缓存条目一样被淘汰。但它将影响该标识前后数据缓存条目的“刷新（Renew）”机制：<strong>比最新的回退点标识更旧的数据缓存条目在“刷新”时并不删除现有的条目，而是新创建一个条目记录最近的内存数据变化</strong>。这是为了保证缓存中的数据能以回退点标识为界限分阶段回退。</p>
<p>OK，现在CPU可以回到先前被中断的流程继续执行了。此后重复上述流程，周而复始的记录下每一个可回退时刻的快照（可以适当限定需保存的快照数上限）。</p>
<p><strong>四. 重回历史轨迹，让Bug无所遁形</strong></p>
<p>当CPU或者软件层的故障捕获机制遇到一个严重异常后，就该让我们的“月光宝盒”发挥奇效了！这时候，首先找出CPU缓存中所记录最早的回退点标识，以此为界，“回写（Flush）”之前的数据缓存项（这一步不是必须的）并丢弃之后的全部缓存项，然后将CPU上下文恢复到前面保存的现场（包括全部寄存器、标志位和内部状态）。</p>
<p>下一个瞬间，我们已然回到了这段程序在它的历史中曾经经历过的瞬间，在继续发动CPU重现历史轨迹之前，请容我们首先准备好必要的故障定位器材，比如开启单步跟踪模式、激活内存读写监视、重定向异常截获入口…… 在可以反复重历的程序轨迹前，相信即使是初出茅庐的程序员也不会再错过任何故障定位信息了。</p>
<p>作为后续拓展空间，我们一方面可以通过优化CPU内部的执行序列（比如结合乱序执行）进一步降低快照动作对程序执行效率的影响；另一方面可以进一步发展出无人干预的自动故障记录和恢复机制，亦或是带有执行回溯能力的“Core Dump”，提高故障定位的便利性。</p>
<p><strong>五. 前路虽多阴霾，却难掩神器之光芒</strong></p>
<p>作为我们力所能及范围之外的IO操作，由于它们可能破坏回退后程序执行路径的确定性，所以在目前的机制里只能以“邪恶”的反面形象出现，每次与它们的照面会使得我们此前辛苦积累起来的全部快照失去意义，不得不再从头来过，这就意味着任何回退企图都无法超越最后一次出现IO操作的时间。虽然通过为IO增设缓存通常能缓解大部分的矛盾，但IO操作的多样化和复杂性使得进一步化解困境努力显得效果甚微。</p>
<p>不过瑕不掩瑜，在CPU执行速度远超IO访问速度的今天，至少从概率学的角度来看，我们所面临的大部分程序执行异常都将出现在远离IO操作的时刻，使得我们仍然有较大的回退空间去捕捉问题。</p>
<p><strong>六. 后记</strong></p>
<p>本文纯属带点技术色彩的调侃和畅想，疏漏、谬误和欠成熟之处在所难免，也欢迎大家加入讨论！相信技术本身总是能在辩论中变得更加清晰和透彻。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oasisfeng.com/2008/07/01/cpu-based-execution-rollback/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.484 seconds -->
