<?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>阿当正传 &#187; Linux tips</title>
	<atom:link href="http://www.adamjiang.com/archives/category/linux-tips/feed" rel="self" type="application/rss+xml" />
	<link>http://www.adamjiang.com</link>
	<description>长脑袋的个人博客</description>
	<lastBuildDate>Wed, 28 Dec 2011 14:18:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>在mutt中使用Gmail地址簿</title>
		<link>http://www.adamjiang.com/archives/1101</link>
		<comments>http://www.adamjiang.com/archives/1101#comments</comments>
		<pubDate>Fri, 23 Dec 2011 06:54:51 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[contact]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mutt]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=1101</guid>
		<description><![CDATA[这又是关于mutt的记事。公司的IT着实非常落后，至今我们仍在使用微软的Office outlook作邮件客户端。没有gmail，没有webmail，倒是直到上周才为每位员工购买了一款叫做Good的Android软件来查看邮件。可是无论怎样，mutt一直是我钟爱的一款邮件客户端。它已经长在我的手指上。现在在公司的开发机器上我已经可以使用IMAP和SMTP收发邮件，也可以在mutt中使用全公司的LDAP来查找地址，所以，整个功能跟低效的Outlook没有区别，处理邮件的速度却比使用Outlook提高了至少两倍。特别是遇到跟工程师之间通信需要贴代码或者发git patch的时候尤其如此。当通过mutt使用自己的gmail的时候，我遇到了一问题，就是Gmail本身并没有提供LDAP接口用来查询地址，于是我无法套用使用公司邮件的配置来查找地址了。昨天在github上发现了一个perl脚本可以解决这个问题。 Gmail提供了API可以帮助外部应用程序取得地址簿中的数据。Ajnasz的这个脚本可以取得地址簿数据并且用查询字符串匹配，从而找到联系人的邮件地址。但是，但是原来的脚本有一个小问题——无法使用中文或者日语姓名作为查询字符串。自己动手，丰衣足食。我在原代码的基础只添加了两行代码，现在查询中文姓名也没有问题了。如果你有兴趣可以从这里拿到代码。 git clone git://github.com/jcadam/Google-Contacts-for-Mutt.git gc-mutt 这个脚本需要一个简单的配置文件用来取得Gmail数据的访问权限。你可以仿照下面这个例子做自己的配置文件。 $ vi ~/.google.ini [account] email = 'youraccount@gmail.com' password = 'Passw0rd' 为了防止其他用户访问你的文件增强安全，你可将文件的属性设置成所有者只读。 $ chmod 400 ~/.google.ini 进入contacts.pl脚本所在目录，然后不带任何参数运行这个脚本，你就可以得到整个Gmail联系人名簿。可以先测试一下。 $ cd $ ./contacts.pl 接着，在PATH变量中的任何一个目录中，通常是/usr/local/bin/或者~/bin，建立一个Shell helper了查询数据。 $ vi ~/bin/contracts #!/usr/bin/env bash ${HOME}/github/gc-mutt/contacts.pl ${1} 然后告诉mutt查询联系人时使用这个helper脚本查询。在~/.muttrc中添加如下一行即可。 set query_command="~/bin/contacts '%s'" 测试一下。在mutt中新建邮件(m)，在To:栏中直接输入联系人的名字，比如”Mark Brown”， 然后按”ctrl-t”查找地址簿。 mutt会自动查询地址布并且取回Mark的邮件地址。]]></description>
			<content:encoded><![CDATA[<p>这又是关于mutt的记事。公司的IT着实非常落后，至今我们仍在使用微软的Office outlook作邮件客户端。没有gmail，没有webmail，倒是直到上周才为每位员工购买了一款叫做Good的Android软件来查看邮件。可是无论怎样，mutt一直是我钟爱的一款邮件客户端。它已经长在我的手指上。现在在公司的开发机器上我已经可以使用IMAP和SMTP收发邮件，也可以在mutt中使用全公司的LDAP来查找地址，所以，整个功能跟低效的Outlook没有区别，处理邮件的速度却比使用Outlook提高了至少两倍。特别是遇到跟工程师之间通信需要贴代码或者发git patch的时候尤其如此。当通过mutt使用自己的gmail的时候，我遇到了一问题，就是Gmail本身并没有提供LDAP接口用来查询地址，于是我无法套用使用公司邮件的配置来查找地址了。昨天在github上发现了一个perl脚本可以解决这个问题。</p>
<p>Gmail提供了API可以帮助外部应用程序取得地址簿中的数据。<a href="https://github.com/Ajnasz">Ajnasz</a>的这个脚本可以取得地址簿数据并且用查询字符串匹配，从而找到联系人的邮件地址。但是，但是原来的脚本有一个小问题——无法使用中文或者日语姓名作为查询字符串。自己动手，丰衣足食。我在原代码的基础只添加了两行代码，现在查询中文姓名也没有问题了。如果你有兴趣可以从<a href="http://github.com/jcadam/Google-Contacts-for-Mutt">这里</a>拿到代码。</p>
<pre>
git clone git://github.com/jcadam/Google-Contacts-for-Mutt.git gc-mutt
</pre>
<p>这个脚本需要一个简单的配置文件用来取得Gmail数据的访问权限。你可以仿照下面这个例子做自己的配置文件。</p>
<pre>
$ vi ~/.google.ini
</pre>
<pre>
[account]
email = 'youraccount@gmail.com'
password = 'Passw0rd'
</pre>
<p>为了防止其他用户访问你的文件增强安全，你可将文件的属性设置成所有者只读。</p>
<pre>
$ chmod 400 ~/.google.ini
</pre>
<p>进入contacts.pl脚本所在目录，然后不带任何参数运行这个脚本，你就可以得到整个Gmail联系人名簿。可以先测试一下。</p>
<pre>
$ cd <where_gc-mutt_is>
$ ./contacts.pl
</pre>
<p>接着，在PATH变量中的任何一个目录中，通常是/usr/local/bin/或者~/bin，建立一个Shell helper了查询数据。</p>
<pre>
$ vi ~/bin/contracts
</pre>
<pre>
#!/usr/bin/env bash
${HOME}/github/gc-mutt/contacts.pl ${1}
</pre>
<p>然后告诉mutt查询联系人时使用这个helper脚本查询。在~/.muttrc中添加如下一行即可。</p>
<pre>
set query_command="~/bin/contacts '%s'"
</pre>
<p>测试一下。在mutt中新建邮件(m)，在<code>To:</code>栏中直接输入联系人的名字，比如”Mark Brown”，</p>
<p><a href="http://www.adamjiang.com/wp-content/uploads/2011/12/mutt-1.png"><img src="http://www.adamjiang.com/wp-content/uploads/2011/12/mutt-1.png" alt="" title="mutt-1" width="595" height="57" class="alignnone size-full wp-image-1103" /></a></p>
<p>然后按”ctrl-t”查找地址簿。</p>
<p><a href="http://www.adamjiang.com/wp-content/uploads/2011/12/mutt-2.png"><img src="http://www.adamjiang.com/wp-content/uploads/2011/12/mutt-2.png" alt="" title="mutt-2" width="422" height="57" class="alignnone size-full wp-image-1104" /></a></p>
<p>mutt会自动查询地址布并且取回Mark的邮件地址。</p>
<p><a href="http://www.adamjiang.com/wp-content/uploads/2011/12/mutt-3.png"><img src="http://www.adamjiang.com/wp-content/uploads/2011/12/mutt-3.png" alt="" title="mutt-3" width="447" height="50" class="alignnone size-full wp-image-1105" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/1101/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Gmail的IMAP和Mutt</title>
		<link>http://www.adamjiang.com/archives/891</link>
		<comments>http://www.adamjiang.com/archives/891#comments</comments>
		<pubDate>Fri, 27 Aug 2010 03:22:01 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=891</guid>
		<description><![CDATA[今天我想说的还是Mutt的问题。一年以前我写了通过mutt使用gmail。现在再回头看这篇文章的内容已经有些老旧了，只好在感慨时光如梭的同时附上更新。电子邮件对我来说越来越重，相应的Mutt这个邮件客户端也是如此。就像Mutt的作者说的，所有的邮件客户端都很烂，只是Mutt烂的不那么厉害罢了。我希望这几篇文章有用。 之前的解决方法相当复杂，需要mutt, procmail, fetchmail和msmtp等等工具的配合，配置起来非常繁琐。使用了很久这个方法之后，我发现还是使用IMAP直接远程接入Gmail比较简便。但是也有相应的缺点，那就是，使用IMAP的话，你就不能在离线状态中使用mutt了。 配置Gmail的IMAP和Mutt一起工作，相比用fetchmail去pop3服务器上的邮件，这个方法主要更改以下几点： 配置Gmail的IMAP 设置远程服务器上的文件夹 设置本地计算机上的缓冲 设置远程服务器上的smtp服务 至于，邮件别名，色彩，和快捷键绑定等等，跟之前介绍的方法并无二致。 配置Gmail的IMAP 创建或者修改~/.muttrc， vi ~/.muttrc 添加如下几行来告诉mutt你是谁，这里设置的姓名和邮件地址将出现在你的邮件的头部； set from = "yourusername@gmail.com" set realname = "yourname" 接着，告诉mutt你Gmail邮箱和密码； set imap_user = "yourusername@gmail.com" set imap_pass = "yourpassword" 在初次启动mutt的时候，mutt会询问你是否接受认证文件，你只需要回答”Yes”就可以了。 设置远程服务器上的文件夹 Mutt可以自动的识别IMAP服务器上的邮件文件夹，所以这里其实不需要更多的动作。但是如果你想做一些自己的配置，可以采用下面的方法； set folder = "imaps://imap.gmail.com:993" set spoolfile = "+INBOX" set postponed ="+[Gmail]/Drafts" set trash = "imaps://imap.gmail.com/[Gmail]/Trash" 设置本地计算机上的缓冲 在本地计算机上，你需要一个缓冲来保存文件头信息，以及TLS证书等； set header_cache =~/.mutt/cache/headers [...]]]></description>
			<content:encoded><![CDATA[<p>今天我想说的还是Mutt的问题。一年以前我写了<a href="http://www.adamjiang.com/archives/33" title="通过mutt使用gmail">通过mutt使用gmail</a>。现在再回头看这篇文章的内容已经有些老旧了，只好在感慨时光如梭的同时附上更新。电子邮件对我来说越来越重，相应的Mutt这个邮件客户端也是如此。就像Mutt的作者说的，所有的邮件客户端都很烂，只是Mutt烂的不那么厉害罢了。我希望这几篇文章有用。</p>
<p>之前的解决方法相当复杂，需要mutt, procmail, fetchmail和msmtp等等工具的配合，配置起来非常繁琐。使用了很久这个方法之后，我发现还是使用IMAP直接远程接入Gmail比较简便。但是也有相应的缺点，那就是，使用IMAP的话，你就不能在离线状态中使用mutt了。</p>
<p>配置Gmail的IMAP和Mutt一起工作，相比用fetchmail去pop3服务器上的邮件，这个方法主要更改以下几点：</p>
<ol>
<li>配置Gmail的IMAP</li>
<li>设置远程服务器上的文件夹</li>
<li>设置本地计算机上的缓冲</li>
<li>设置远程服务器上的smtp服务</li>
</ol>
<p>至于，邮件别名，色彩，和快捷键绑定等等，跟<a href="http://www.adamjiang.com/archives/33" title="通过mutt使用gmail">之前介绍</a>的方法并无二致。</p>
<p><strong>配置Gmail的IMAP</strong><br />
创建或者修改<code>~/.muttrc</code>，</p>
<pre>
vi ~/.muttrc
</pre>
<p>添加如下几行来告诉mutt你是谁，这里设置的姓名和邮件地址将出现在你的邮件的头部；</p>
<pre>
set from = "yourusername@gmail.com"
set realname = "yourname"
</pre>
<p>接着，告诉mutt你Gmail邮箱和密码；</p>
<pre>
set imap_user = "yourusername@gmail.com"
set imap_pass = "yourpassword"
</pre>
<p>在初次启动mutt的时候，mutt会询问你是否接受认证文件，你只需要回答”Yes”就可以了。</p>
<p><strong>设置远程服务器上的文件夹</strong><br />
Mutt可以自动的识别IMAP服务器上的邮件文件夹，所以这里其实不需要更多的动作。但是如果你想做一些自己的配置，可以采用下面的方法；</p>
<pre>
set folder = "imaps://imap.gmail.com:993"
set spoolfile = "+INBOX"
set postponed ="+[Gmail]/Drafts"
set trash = "imaps://imap.gmail.com/[Gmail]/Trash"
</pre>
<p><strong>设置本地计算机上的缓冲</strong><br />
在本地计算机上，你需要一个缓冲来保存文件头信息，以及TLS证书等；</p>
<pre>
set header_cache =~/.mutt/cache/headers
set message_cachedir =~/.mutt/cache/bodies
set certificate_file =~/.mutt/certificates
</pre>
<p>别忘了创建相应的本地文件夹</p>
<pre>
mkdir -p ~/.mutt/cache
</pre>
<p><strong>设置远程服务器上的smtp服务</strong><br />
设置smtp服务器用来发送邮件</p>
<pre>
set smtp_url = "smtp://yourusername@smtp.gmail.com:587/"
set smtp_pass = "yourpassword"
</pre>
<p><strong>其他设置</strong><br />
告诉Mutt不要将邮件移动的mbox里，同时为了增强安全性，设置连续上线时间不超过900分钟；</p>
<pre>
set move = no
set imap_keepalive = 900
</pre>
<p>让mutt的配置文件成为“只读”属性。</p>
<pre>
chmod 700 .muttrc
</pre>
<p>配置结束。关于诸如色彩，快捷键，邮件编辑器等其他部分的配置，请参考<a href="http://www.adamjiang.com/_muttrc" title="my mutt configuration">我的mutt配置文件</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/891/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>纪念MacOS 9</title>
		<link>http://www.adamjiang.com/archives/881</link>
		<comments>http://www.adamjiang.com/archives/881#comments</comments>
		<pubDate>Thu, 10 Jun 2010 03:11:49 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[OS 9]]></category>
		<category><![CDATA[Screenshot]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=881</guid>
		<description><![CDATA[嘿，我得承认我是半个水果迷。昨天偶尔在Apple4us看到WWDC的历史中提到MacOS 9，才发现图形用户界面最初的样子是那么迷人。于是，我决定将我的GNU/Linux打扮成MacOS 9的样子。Here comes my lovely screenshot.]]></description>
			<content:encoded><![CDATA[<p>嘿，我得承认我是半个水果迷。昨天偶尔在Apple4us看到WWDC的历史中提到MacOS 9，才发现图形用户界面最初的样子是那么迷人。于是，我决定将我的GNU/Linux打扮成MacOS 9的样子。Here comes my lovely screenshot.</p>
<p><a href="http://www.adamjiang.com/wp-content/uploads/2010/06/MacOs-9-like-screen.png"><img class="size-medium wp-image-882 alignnone" title="MacOs-9-like-screen" src="http://www.adamjiang.com/wp-content/uploads/2010/06/MacOs-9-like-screen-300x225.png" alt="MacOs 9 on Gnome" width="300" height="225" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/881/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>﻿Gmail证书变更导致的msmtp错误</title>
		<link>http://www.adamjiang.com/archives/858</link>
		<comments>http://www.adamjiang.com/archives/858#comments</comments>
		<pubDate>Fri, 28 May 2010 09:56:45 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mutt]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=858</guid>
		<description><![CDATA[大约一年前我写了《通过mutt使用gmail》，之后因为更换新机器有没有时间再将 mutt等工具配置起来；今天重新在新的gentoo系统上配置Mutt使用gmail却发现原 来的方法出错了。 错误消息如下 msmtp: TLS certificate verification failed: the certificate hasn’t got a known issuer. 很显然，google将gmail的cert变更了。单纯的使用msmtp确认一下： % msmtp --serverinfo --host=smtp.gmail.com --tls=on --port=587 --tls-certcheck=off SMTP server at smtp.gmail.com ([74.125.53.109]), port 587: mx.google.com ESMTP r20sm18086225wam.17 TLS certificate information: Owner: Common Name: smtp.gmail.com Organization: Google Inc Locality: Mountain View State or Province: California Country: US Issuer: Common [...]]]></description>
			<content:encoded><![CDATA[<p>大约一年前我写了《<a title="通过mutt使用gmail" href="http://www.adamjiang.com/archives/33" target="_blank">通过mutt使用gmail</a>》，之后因为更换新机器有没有时间再将</p>
<p>mutt等工具配置起来；今天重新在新的gentoo系统上配置Mutt使用gmail却发现原<br />
来的方法出错了。</p>
<p>错误消息如下</p>
<pre>msmtp: TLS certificate verification failed: the certificate hasn’t got a
known issuer.</pre>
<p>很显然，google将gmail的cert变更了。单纯的使用msmtp确认一下：</p>
<pre>% msmtp --serverinfo --host=smtp.gmail.com --tls=on --port=587 --tls-certcheck=off
SMTP server at smtp.gmail.com ([74.125.53.109]), port 587:
    mx.google.com ESMTP r20sm18086225wam.17
TLS certificate information:
    Owner:
        Common Name: smtp.gmail.com
        Organization: Google Inc
        Locality: Mountain View
        State or Province: California
        Country: US
    Issuer:
        Common Name: Google Internet Authority
        Organization: Google Inc
        Country: US
    Validity:
        Activation time: 2010年04月23日 05時02分45秒
        Expiration time: 2011年04月23日 05時12分45秒
    Fingerprints:
        SHA1: 1A:6F:48:8F:BE:5B:FD:92:D8:12:30:F9:22:CE:84:49:B3:43:BD:2C
        MD5:  60:39:DE:FB:0A:D9:9E:43:26:E7:75:AC:60:48:A1:B0
Capabilities:
    SIZE 35651584:
        Maximum message size is 35651584 bytes = 34.00 MB
    STARTTLS:
        Support for TLS encryption via the STARTTLS command
    AUTH:
        Supported authentication methods:
        PLAIN LOGIN</pre>
<p>之前使用过的Thwate Server已经过期了，Issuer字段变成了由google之间给<br />
cert。:(</p>
<p>幸好，修复这个错误非常容易，在debain或者ubuntu系统上可以安装<br />
ca-certificates包来修复这个错误。</p>
<pre># sudo apt-get install ca-certificates
# dpkg -s ca-certificates | grep Version
Version: 20090814</pre>
<p>然后，只要更改~/.msmtprc文件就可以了，将tls_trust_file改正为</p>
<pre>tls_trust_file /usr/share/ca-certificates/mozilla/Equifax_Secure_CA.crt</pre>
<p>gentoo用户需要将这个文件download下来，并且重新指定tls的位置：</p>
<p><a href="http://sysinf0.klabs.be/usr/share/ca-certificates/mozilla/Equifax_Secure_CA.crt?f=download;dist=etch;component=main;arch=i386;pkg=ca-certificates;ver=20070303" title="Equifax_Secure_CA.crt"></p>
<p>http://sysinf0.klabs.be/usr/share/ca-certificates/mozilla/Equifax_Secure_CA.crt?f=download;dist=etch;component=main;arch=i386;pkg=ca-certificates;ver=20070303</p>
<p></a></p>
<p>P.S. 博客并不适合用来记录这样内容，但是，前一篇gmail相关文章已经贴到了博<br />
客，照例还是帖一篇上来吧，各位见谅。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/858/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>配置Ubuntu Jaunty和双显示器一起工作</title>
		<link>http://www.adamjiang.com/archives/643</link>
		<comments>http://www.adamjiang.com/archives/643#comments</comments>
		<pubDate>Sat, 18 Jul 2009 10:18:56 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[3D]]></category>
		<category><![CDATA[Dual Monitor]]></category>
		<category><![CDATA[Geek]]></category>
		<category><![CDATA[GFX]]></category>
		<category><![CDATA[Intel]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=643</guid>
		<description><![CDATA[OK. 这一篇的主旨只是为了记录我解决问题的过程。 关闭FrameBuffer设备 上周星期五，我以一千元人民币的价格淘到了垂涎已久的22存高清显示器。今天早晨送到家里，我自然是兴奋不已的打开看了。Ubuntu Jaunty启动之后可以很顺利的识别外接显示器，但是外接显示器的分辨率却不正确。使用xrandr查看，发现整个设备的大小受到限制。Thinkpad X61的spec上写的很清楚，整个图形卡的最大可表现区域是因该是外接显示器于笔记本固有显示器面积的总和，也就是2944&#215;1080。使用xrandr -q查看，发现这个最大值并没有被正确设置。less /etx/X11/xorg.conf看到，配置文件中启用了FrameBuffer设备。立即恍然大悟。原来，早些日子，我在控制台上工作的时候，启用了FrameBuffer来获得更大的显示区域。为了支持这个控制台显示区域，X服务器只能割让一部分显示存储给FrameBuffer设备。要修改回来就是在内核参数行去掉vga=791选项——这个选项代表1024&#215;768的FrameBuffer能力。并且，重新启动机器之后，利用sudo dpkg-reconfigure -phigh xserver-xorg来重新配制xserver。因为，从Ubuntu 8.10版本开始，这个发行版中启用了新的xserver，所以，大部分配置可以由xserver自动完成，不需要再手动更改xorg.conf配置文件了。重启xserver之后，我再用xrandr -q查看了设备能力，输入如下。这是保证双显示器expand输出的前提条件。 $ xrandr -q Screen 0: minimum 320 x 200, current 2944 x 1080, maximum 4096 x 4096 VGA connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm 1920x1080 60.0*+ 1280x1024 75.0 60.0 1152x864 75.0 1024x768 75.0 60.0 800x600 [...]]]></description>
			<content:encoded><![CDATA[<p>OK. 这一篇的主旨只是为了记录我解决问题的过程。</p>
<h3>关闭FrameBuffer设备</h3>
<p>上周星期五，我以一千元人民币的价格淘到了垂涎已久的22存高清显示器。今天早晨送到家里，我自然是兴奋不已的打开看了。Ubuntu Jaunty启动之后可以很顺利的识别外接显示器，但是外接显示器的分辨率却不正确。使用xrandr查看，发现整个设备的大小受到限制。<a href="http://www-06.ibm.com/jp/pc/notebooks/thinkpad/x-series/x61_lineup_4x.shtml">Thinkpad X61的spec</a>上写的很清楚，整个图形卡的最大可表现区域是因该是外接显示器于笔记本固有显示器面积的总和，也就是2944&#215;1080。使用<code>xrandr -q</code>查看，发现这个最大值并没有被正确设置。<code>less /etx/X11/xorg.conf</code>看到，配置文件中启用了FrameBuffer设备。立即恍然大悟。原来，早些日子，我在控制台上工作的时候，启用了FrameBuffer来获得更大的显示区域。为了支持这个控制台显示区域，X服务器只能割让一部分显示存储给FrameBuffer设备。要修改回来就是在内核参数行去掉vga=791选项——这个选项代表1024&#215;768的FrameBuffer能力。并且，重新启动机器之后，利用<code>sudo dpkg-reconfigure -phigh xserver-xorg</code>来重新配制xserver。因为，从Ubuntu 8.10版本开始，这个发行版中启用了新的xserver，所以，大部分配置可以由xserver自动完成，不需要再手动更改xorg.conf配置文件了。重启xserver之后，我再用<code>xrandr -q</code>查看了设备能力，输入如下。这是保证双显示器expand输出的前提条件。</p>
<pre>
$ xrandr -q
Screen 0: minimum 320 x 200, current 2944 x 1080, maximum 4096 x 4096
VGA connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm
   1920x1080      60.0*+
   1280x1024      75.0     60.0
   1152x864       75.0
   1024x768       75.0     60.0
   800x600        75.0     60.3
   640x480        75.0     59.9
   720x400        70.1
LVDS connected 1024x768+1920+0 (normal left inverted right x axis y axis) 246mm x 185mm
   1024x768       50.0 +   85.0*    75.0     70.1     60.0     40.0
   832x624        74.6
   800x600        85.1     72.2     75.0     60.3     56.2
   640x480        85.0     72.8     75.0     59.9
   720x400        85.0
   640x400        85.1
   640x350        85.1
</pre>
<h3>配置双显示器expand表示</h3>
<p>利用<code>gnome-display-properties</code>，我可以在这里动态的设置双显示的规格。有图为证。<br />
<img src="http://lh4.ggpht.com/_O-FwCW3mN_w/SmGe5HBeVuI/AAAAAAAAEQo/8pbjHGx86HM/gnome-display-properties.png" /><br />
如果这个方法受限，那么还有一个后背方案，就是采用<a href="http://intellinuxgraphics.org/dualhead.html">Intel显卡驱动官方站的指南</a>，采用xrandr来手动配置。</p>
<h3>更新Mesa</h3>
<p>设置双显示expand之后，我发现小显示器的一部分不能正确更新。初次看到这个现象的时候，我开始怀疑是不是设备能力有限，不能支持这么大的屏幕显示区域。但是仔细计算了一下，这种情况应该是不可能发生的。我的图形卡支持的最大输出是2944&#215;1080，那么宽度上1920+1024不会超过这个2944，而长度来看768小于1080。那问题出在哪里呢？我尝试关闭了“桌面效果”，也就是启用metacity来取代compiz做窗口管理器。我发现这样的话两个屏幕都是可以被正确更新的。立刻想到问题应该处在3D表示的驱动上面。也就是作为3D表示基础库的Mesa有问题。找到关键词就很容易搜索了，google之。立刻发现这个问题是出现在<a href="https://bugs.freedesktop.org/show_bug.cgi?id=18100">mesa-7.4版本之中的bug</a>。而这个bug已经被修复了。这个时候，我想是不是可以拿到mesa的源代码，然后给它打上补丁后重新package。于是立刻行动，我用<code>apt-get source libgl1-mesa-dev libgl1-mesa-dri</code>那到mesa的源代码，照猫画虎的打补丁。转念一下，这个问题应该已经有很多人遇到了，因为Jaunty发布已经有近4个月的时间，不会只有我遇到这个问题。于是乎，我在launchpad上搜索一下，发现果然有<a href="https://launchpad.net/~xorg-edgers/+archive/ppa">新版本的mesa</a>可以使用。因为这个PPA提供的是unstable版本软件包，所以该PPA的作者声明拒绝外部资源直接给出该PPA的使用方法用来保证每个用户都可以读到警告信息。这里就不再说到底怎么使用了。如果你想在Ubuntu中使用fresh的xorg相关软件包，那么直接点下面的连接跳转过去看看吧。<br />
<a href="https://launchpad.net/~xorg-edgers/+archive/ppa">https://launchpad.net/~xorg-edgers/+archive/ppa</a></p>
<p>经过以上步骤的折腾之后，我的Ubuntu就可以使用双显示器正常工作了。写代码的时候再也不需要挤在那个1024&#215;768的显示器上用Alt+Tab换来换去了。还有就是玩企鹅滑冰有些就更爽了。（话外音：真浪费）同学，我听见了，虽然这个安装过程还是遇到问题多多，但是谁让俺自己愿意折腾呢？由此可证，所有的GNU/Linux用户都是那“吃饱了没事撑着”的某些人。</p>
<p>&#8211;<br />
参考URL：<br />
<a href="http://lists.freedesktop.org/archives/xorg/2008-April/034707.html">http://lists.freedesktop.org/archives/xorg/2008-April/034707.html</a><br />
<a href="http://www.thinkwiki.org/wiki/Xorg_RandR_1.2#Summing_up">http://www.thinkwiki.org/wiki/Xorg_RandR_1.2#Summing_up</a><br />
<a href="https://bugs.launchpad.net/ubuntu/+source/mesa/+bug/146298">https://bugs.launchpad.net/ubuntu/+source/mesa/+bug/146298</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/643/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Emacs——很漂亮很强大</title>
		<link>http://www.adamjiang.com/archives/622</link>
		<comments>http://www.adamjiang.com/archives/622#comments</comments>
		<pubDate>Sat, 11 Jul 2009 13:32:07 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[Emacs]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=622</guid>
		<description><![CDATA[Vim我用了5年有余，最近因为接触的项目非常大，大约10W行代码，而且该项目采用包括C和C++还有python的多种语言开发，突然让我觉得使用Vim有些应付不过来。我的主要任务并不是去查看系统细节，而是要在短时间内获得已有系统的情况——包括结构和功能上的信息，所以我需要一个比较强大的代码浏览程序。公司提供的软件库里面搜索了半天，找到十几款代码浏览工具竟然没有一款是我熟悉的。一狠心，我觉得尝试一下Emacs。或许Vim也能够胜任这个工作，但是我尝试拼凑了很久插件也没能找到符合工作需要的集合。总之，破釜沉舟，试一下Emacs。谁知道上手之后我竟然再也放不下Emacs了，彻底被这款编辑器的扩展性和强大功能征服。在使用了Emacs一个月以后，对于我的“重大发现”，我想还是留下一个记录比较好。 基础软件包 $ sudo apt-get install emacs-snapshot emacs-snapshot-common emacs-snapshot-bin-common emacs-snapshot-el emacs-goodies-el emacs-snapshot-gtk 漂亮的Emacs 我并不是个特别喜欢冒险的人，所以刚刚开始的时候，我选择了Emacs22。但是，后来发现，处理日语和中文的字体显示非常繁琐，索性放弃“保守派”的一贯作风，跃迁到还在开发中的Emacs23。在google上搜索得到Alexandre Vassalotti写的很流行的一篇博文Pretty Emacs，如法炮制，在Ubuntu 9.04上得到了一个让我基本满意的操作界面。这篇博文虽然有用但却非常简略，并没有详细说明CJK字体的反锯齿应该怎样处理。我尝试在~/.Xresource文件中使用包含日语和中文的字体，但是结果并不能让我满意，原因是日语和中文的汉字显示混在了一起，错别字太多。拜google所赐，最终还是找到了解决之法。证据在此。 在.emacs中需要使用字符集来将日语和中文的显示字符区别对待，代码如下： ;;;------------------------------------------------------------;;; ;;; VIEW ;;; No startup message (setq inhibit-startup-message t) ;;; GUI font (set-default-font "Bitstream Vera Sans Mono-12") ;;; JP fonts (set-fontset-font (frame-parameter nil 'font) 'japanese-jisx0208 '("M+2VM+IPAG circle" . "unicode-bmp")) ;;; zh-CN fonts (set-fontset-font (frame-parameter nil 'font) [...]]]></description>
			<content:encoded><![CDATA[<p>Vim我用了5年有余，最近因为接触的项目非常大，大约10W行代码，而且该项目采用包括C和C++还有python的多种语言开发，突然让我觉得使用Vim有些应付不过来。我的主要任务并不是去查看系统细节，而是要在短时间内获得已有系统的情况——包括结构和功能上的信息，所以我需要一个比较强大的代码浏览程序。公司提供的软件库里面搜索了半天，找到十几款代码浏览工具竟然没有一款是我熟悉的。一狠心，我觉得尝试一下Emacs。或许Vim也能够胜任这个工作，但是我尝试拼凑了很久插件也没能找到符合工作需要的集合。总之，破釜沉舟，试一下Emacs。谁知道上手之后我竟然再也放不下Emacs了，彻底被这款编辑器的扩展性和强大功能征服。在使用了Emacs一个月以后，对于我的“重大发现”，我想还是留下一个记录比较好。</p>
<h3>基础软件包</h3>
<p><code><br />
$ sudo apt-get install emacs-snapshot emacs-snapshot-common emacs-snapshot-bin-common emacs-snapshot-el emacs-goodies-el emacs-snapshot-gtk<br />
</code></p>
<h3>漂亮的Emacs</h3>
<p>我并不是个特别喜欢冒险的人，所以刚刚开始的时候，我选择了Emacs22。但是，后来发现，处理日语和中文的字体显示非常繁琐，索性放弃“保守派”的一贯作风，跃迁到还在开发中的Emacs23。在google上搜索得到<a href="http://images.google.co.jp/imgres?imgurl=http://farm4.static.flickr.com/3346/3336195816_817511aa10_o.jpg&amp;imgrefurl=http://flickr.com/photos/sfllaw/3336195816/&amp;usg=__v9gDhwGunQ6e7XAvLyDSFBUp0Ys=&amp;h=4368&amp;w=2912&amp;sz=73&amp;hl=ja&amp;start=9&amp;sig2=c9ZFxGdvK-qzSq3deq9-FQ&amp;um=1&amp;tbnid=3z99E0FRZYeH6M:&amp;tbnh=150&amp;tbnw=100&amp;prev=/images%3Fq%3DAlexandre%2BVassalotti%26hl%3Dja%26client%3Dfirefox-a%26rls%3Dcom.ubuntu:ja:unofficial%26sa%3DN%26um%3D1&amp;ei=lnhYSpfmAobmtgPJ5czIAg">Alexandre Vassalotti</a>写的很流行的一篇博文<a href="http://peadrop.com/blog/2007/01/06/pretty-emacs/">Pretty Emacs</a>，如法炮制，在Ubuntu 9.04上得到了一个让我基本满意的操作界面。这篇博文虽然有用但却非常简略，并没有详细说明CJK字体的反锯齿应该怎样处理。我尝试在~/.Xresource文件中使用包含日语和中文的字体，但是结果并不能让我满意，原因是日语和中文的汉字显示混在了一起，错别字太多。拜google所赐，最终还是找到了解决之法。证据在此。</p>
<p><a href="http://lh6.ggpht.com/_O-FwCW3mN_w/SliQpLvR2-I/AAAAAAAAEPo/bQWHMJ_6SJ8/Screenshot-emacs-3.png"><img title="Emacs screenshot" src="http://lh6.ggpht.com/_O-FwCW3mN_w/SliQpLvR2-I/AAAAAAAAEPo/bQWHMJ_6SJ8/s400/Screenshot-emacs-3.png" alt="" /></a></p>
<p>在.emacs中需要使用字符集来将日语和中文的显示字符区别对待，代码如下：</p>
<pre>;;;------------------------------------------------------------;;;
;;; VIEW
;;; No startup message
(setq inhibit-startup-message t)
;;; GUI font
(set-default-font "Bitstream Vera Sans Mono-12")
;;; JP fonts
(set-fontset-font (frame-parameter nil 'font)
		  'japanese-jisx0208
		  '("M+2VM+IPAG circle" . "unicode-bmp"))
;;; zh-CN fonts
(set-fontset-font (frame-parameter nil 'font)
		  'han
		  '("Vera Sans YuanTi Mono" . "unicode-bmp"))
;;;;===========================================================;;;;
;;; cjk-misc fonts
(set-fontset-font (frame-parameter nil 'font)
		  'cjk-misc
		  '("Vera Sans YuanTi Mono" . "unicode-bmp"))
;;; bopomofo fonts
(set-fontset-font (frame-parameter nil 'font)
		  'bopomofo
		  '("Vera Sans YuanTi Mono" . "unicode-bmp"))
;;; symbol fonts
(set-fontset-font (frame-parameter nil 'font)
		  'symbol
		  '("Vera Sans YuanTi Mono" . "unicode-bmp"))
;;;;=========================================================;;;;</pre>
<p>“Vera Sans YuanTi”字体似乎涉嫌侵权，所以现在在互联网上已经难觅其踪，但是我还是非常喜欢这款合成字体，三四年前私自收藏了一直使用。在Ubuntu Jaunty上，读者可以尝试使用文泉驿等字体替代。或者，如果你拥有Windows的授权，使用微软雅黑也会有不错的效果。这里需要注意的是，Ubuntu 8.04或者更早版本上的emacs-snapshot提供的Emacs版本并不支持CJK字体的反锯齿显示。如果你使用比较早版本的Emacs23，可以尝试使用<a href="http://emacs.orebokech.com/">emacs.orebokech.com</a>提供的WeeklyBuild。但是事先应该确认一下在Ubuntu的backport上有没有提供emacs-snapshot的软件包。下面是中文显示效果的截屏。</p>
<p><a href="http://lh4.ggpht.com/_O-FwCW3mN_w/SliRUu1hspI/AAAAAAAAEPs/URgQ7TazitA/Screenshot-emacs-4.png"><img title="Emacs Screenshot Display Chinese" src="http://lh4.ggpht.com/_O-FwCW3mN_w/SliRUu1hspI/AAAAAAAAEPs/URgQ7TazitA/s400/Screenshot-emacs-4.png" alt="" /></a></p>
<h3>安装CEDET</h3>
<p><a href="http://cedet.sourceforge.net/">CEDET</a>是一整套开发环境的集合工具。包括工程管理，代码浏览和自动补全工具。但是，Ubuntu的软件频道中提供的版本并不能和Emacs23一起工作。详情可以看这个Debian的<a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525613">Bug#525613</a>。我的解决办法是采用新的CEDET版本。<br />
<code><br />
$ wget http://sourceforge.net/projects/cedet/files/cedet/cedet-1.0pre6.tar.gz/download<br />
$ tar zxf cedet-1.0pre6.tar.gz<br />
$ cd cedet-1.0pre6/<br />
$ make<br />
$ make install-info<br />
$ cd ../ &amp;&amp; cp -a cedet-1.0pre6 /usr/share/emacs-snapshot/site-lisp/cedet<br />
</code><br />
这里需要注意的是，必须将编译好的cedet拷贝到/usr/share/emacs-snapshot/site-lisp中，而不能仅仅将这个文件放到load-path中了事。原因是Emacs在初始化的时候，会利用这个目录中的subdirs.el来保证整个目录都添加进入load-path之中。接下来在.emacs中添加下面这几行就基本可以使用了，但是上手之后应该多查看info的内容找到更多的信息。在Emacs中利用组合键Ctrl-h i可以打开info，按s查找CEDET。</p>
<pre>;;;-----------------------------------------------------------------;;;
;;; CEDET
;;;-----------------------------------------------------------------;;;
;; Load CEDET.
;; See cedet/common/cedet.info for configuration details.
(require 'cedet)

;; Enable EDE (Project Management) features
(global-ede-mode 1)

;; Enable EDE for a pre-existing C++ project
;; (ede-cpp-root-project "NAME" :file "~/myproject/Makefile")

;; Enabling Semantic (code-parsing, smart completion) features
;; Select one of the following:

;; * This enables the database and idle reparse engines
(semantic-load-enable-minimum-features)

;; * This enables some tools useful for coding, such as summary mode
;;   imenu support, and the semantic navigator
(semantic-load-enable-code-helpers)</pre>
<p>CEDET非常强大，以至于很难几句话将这个工具讲清楚，但是经常查看info和多多实践，马上就会用的非常顺手。</p>
<h3>后记</h3>
<p>最近一些日子，我一直在看Emacs相关的内容。Emacs可以说不仅仅是一款编辑器，而是一个集成并且可以扩展的工作环境。很多年轻的程序员，包括我自己，总是在各种各样的工具之间跳来跳去，一方面可以是因为自己不够坚定，但另一方面只能说很多工具都有自己的局限性，当程序员遇到新的情况的时候就可能很自然的抛弃旧工具。Emacs却不同，它更像一个framework，你可以将自己的技巧，使用习惯以及效率提升工具全部集成其上。如果它不够用了，你可以自己动手写lisp对它进行扩展。又想起那句话，人们往往高估自己短期的能力而低估自己长期的积累。Emacs正是给这种积累提供一种可能性。也许这正是对我来说最要命特性。我的.emacs文件在<a href="https://github.com/jcadam/pemacs/blob/master/_emacs">这里</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/622/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Linux的精灵（daemon）进程和僵尸（zombie）进程</title>
		<link>http://www.adamjiang.com/archives/599</link>
		<comments>http://www.adamjiang.com/archives/599#comments</comments>
		<pubDate>Sat, 27 Jun 2009 07:11:38 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[嵌入式Linux]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/?p=599</guid>
		<description><![CDATA[有些日子没有跟工程师一起工作了。昨天星期五，我回到川崎的办公室和同事一起结果一个客户反馈的问题。这个工作却又让我怀念以前作研发的那些时光。突然觉得有些东西还是不应该被忘记，就写在这里作笔记了。 守护进程(Daemon) 守护进程——我情愿把他叫做精灵进程——是多种操作系统中的一种常驻程序。常驻的意思是，在系统运行期间，这些进程都一直存在。很明显，大多数服务器程序都是精灵进程。在这里我要说一说自己知道关于精灵进程的方法，和与此相关的一些技巧。 如何产生一个精灵进程？ Linux系统启动以后，它通常启动的第一个进程就是init进程。init进程的进程ID是1，并且它会一直在系统运行期间存续。同时，Linux对进程的管理策略有两个比较特殊的地方，其中之一就是，当一个进程的父进程结束，它的子进程如果还继续运行，那么，子进程就会被init进程收养。也算就是说，Linux对进程的管理策略，其实是一直在努力维护一棵树。利用这一点，就可产生伴随init一直存在的精灵进程。代码例子如下： /* file: daemon_sample.c */ #include #include #include #include int main () { pid_t pid,sid; /* fork to leave parent */ pid = fork (); if (pid &#60; 0) { printf ("failed to fork!\n"); exit (EXIT_FAILURE); } else if (pid &#62; 0) { /* parent process go to exit */ exit [...]]]></description>
			<content:encoded><![CDATA[<p>有些日子没有跟工程师一起工作了。昨天星期五，我回到川崎的办公室和同事一起结果一个客户反馈的问题。这个工作却又让我怀念以前作研发的那些时光。突然觉得有些东西还是不应该被忘记，就写在这里作笔记了。</p>
<h3>守护进程(Daemon)</h3>
<p>守护进程——我情愿把他叫做精灵进程——是多种操作系统中的一种常驻程序。常驻的意思是，在系统运行期间，这些进程都一直存在。很明显，大多数服务器程序都是精灵进程。在这里我要说一说自己知道关于精灵进程的方法，和与此相关的一些技巧。</p>
<h3>如何产生一个精灵进程？</h3>
<p>Linux系统启动以后，它通常启动的第一个进程就是init进程。init进程的进程ID是1，并且它会一直在系统运行期间存续。同时，Linux对进程的管理策略有两个比较特殊的地方，其中之一就是，当一个进程的父进程结束，它的子进程如果还继续运行，那么，子进程就会被init进程收养。也算就是说，Linux对进程的管理策略，其实是一直在努力维护一棵树。利用这一点，就可产生伴随init一直存在的精灵进程。代码例子如下：</p>
<pre>/* file: daemon_sample.c */
#include
#include
#include
#include 

int main ()
{
	pid_t	pid,sid;

	/* fork to leave parent */
	pid = fork ();
	if (pid &lt; 0) {
		printf ("failed to fork!\n");
		exit (EXIT_FAILURE);
	} else if (pid &gt; 0) {
		/* parent process go to exit */
		exit (EXIT_SUCCESS);
	}

	/* child process */
	chdir("/");
	sid = setsid ();
	if (sid &lt; 0) {
		printf ("Failed to set session id.\n");
		exit (EXIT_FAILURE);
	}
	/* ensure all files created by itself are accessible */
	umask (0);

	printf ("Daemon adopted by parent %d\n", getppid());

	/* daemon loop */
	while (1) {
		sleep (1);
	}
}</pre>
<p>产生一个精灵进程的过程需要有一下几步：</p>
<ol>
<li>从启动该程序的进程中fork出来一个子进程；如果子进程产生成功，那么就将父进程结束</li>
<li>子进程需要作一些处理来保证自己作为精灵的地位；改变当前工作目录；利用setsid系统调用重新设置一个session；利用umask系统调用消除父进程对于文件控制的影响，从而保证精灵可以正确的访问它自己生成的各种文件——其中比较重要的是IPC</li>
<li>子进程需要启动一个自身处理的循环</li>
</ol>
<p>这是一个非常简单的例子，通常情况下，子进程还需要关闭标准输入输出等等工作。与此相关的详细讨论可以查看<br />
<a title="Linux Daemon Writing Howto" href="http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html">http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html</a><br />
这里有一个可以下载到本地的PDF版本<br />
<a title="Linux Daemon Writing Howto" href="http://www.google.co.jp/url?sa=t&amp;source=web&amp;ct=res&amp;cd=2&amp;url=http%3A%2F%2Fwww.cs.aau.dk%2F~adavid%2Fteaching%2FMTP-05%2Fexercises%2F10%2FLinux-Daemon_Writting.pdf&amp;ei=W7pFSreDHoTW7APC0_Eh&amp;usg=AFQjCNHyZnXmdKL8ebxJ8UXQsYeGHiqRwQ&amp;sig2=7Of2PvUnmTm8xqZifI-aAw">http://www.google.co.jp/url?sa=t&amp;source=web&amp;ct=res&amp;cd=2&amp;url=http%3A%2F%2Fwww.cs.aau.dk%2F~adavid%2Fteaching%2FMTP-05%2Fexercises%2F10%2FLinux-Daemon_Writting.pdf&amp;ei=W7pFSreDHoTW7APC0_Eh&amp;usg=AFQjCNHyZnXmdKL8ebxJ8UXQsYeGHiqRwQ&amp;sig2=7Of2PvUnmTm8xqZifI-aAw</a></p>
<h3>怎样判断一个进程是否是精灵进程？</h3>
<p>恩，奇怪的地方就在与此了。如果用如下命令编译上面的简短程序，你会发现一处不太符合想象的地方。<br />
<code><br />
$ gcc -o daemon_sample daemon_sample.c<br />
</code><br />
在终端窗口中运行这个程序，然后我们作一些观察。<br />
<code><br />
$ ./daemon_sample<br />
</code><br />
按照上面我叙述过的内容，这个程序的将被init进程收养。那么，理所当然的它的父进程ID应该是“1”。然而，这个程序运行时却抛出了这样一句话。<br />
<code><br />
Daemon adopted by parent 29914<br />
</code><br />
这里的29914是通过getppid()取得的，难道有什么不对头？为了确认情况，再用ps查看一下究竟发生了什么事情。<br />
<code><br />
$ ps -e -o pid,ppid,cmd,tty | grep daemon_sample<br />
29915     1 ./daemon_sample             ?<br />
</code><br />
利用ps命令的-o选项，可以查看进程的pid,ppid,命令行和运行终端的信息。显而易见，这个精灵进程事实上的ppid是“1”。那么，为什么getppid()不能返回正确的值？难道这里是个BUG？就目前Linux内核的状况来说，这不是一个BUG，查看getppid的手册页可以看到，getppid并不保证能够取得一个进程被收养以后的父进程ID。或者有兴趣的xdjm可以尝试一下将这个功能升级一下:)。</p>
<p>换句话说，不能使用getppid来判断一个进程时候是精灵进程。那么，应该怎样判断？</p>
<p>再看上面ps的输出结果，你会发现这个进程的tty域是一个问号。这表明，该进程并没有被attach到任何终端设备上去。事实上所有的精灵进程都有这个特性。利用ps做一个验证吧。<br />
<code><br />
$ ps -e -o pid,ppid,cmd,tty | grep daemon<br />
898     1 /sbin/udevd --daemon        ?<br />
2464     1 /bin/dbus-daemon --system   ?<br />
3305     1 avahi-daemon: running [capr ?<br />
3829     1 //bin/dbus-daemon --fork -- ?<br />
29915     1 ./daemon_sample             ?<br />
31584 29871 grep --color=auto daemon    pts/1<br />
</code><br />
这里有ps命令的结果，它被attach到伪终端pts/1。所以，可以利用这个特性来判断一个进程是否是精灵进程。</p>
<pre>if ((devtty = open ("/dev/tty", O_RDWD)) &lt; 0) {
   printf ("This is a daemon\n");
} else {
   printf ("This is not a daemon\n");
}</pre>
<p>在UNIX论坛上有一个关于这个话题的旧帖子，地址如下：<br />
<a title="How to find if a process a daemon?" href="http://www.unix.com/high-level-programming/72479-how-find-if-process-daemon.html">http://www.unix.com/high-level-programming/72479-how-find-if-process-daemon.html</a><br />
精灵进程大致就是这样。</h3>
<h3>僵尸进程</h3>
<p>僵尸进程其实是个错误。</p>
<p>这个错误产生的原因在于，子进程已经结束，但是父进程却没有对它进行清理。僵尸进程会被init收编，并且init会料理这些僵尸的“善后事宜”。我们可以写一个很蹩脚的程序来产生一个货真价实的僵尸进程。僵尸来了！</p>
<pre>/* file: zombie.c */
#include
#include
#include 

int main ()
{
	pid_t child_pid;

	/* Create a child process. */
	child_pid = fork ();
	if (child_pid &gt; 0) {
	   /* This is the parent process. Sleep for a minitue. */
	   sleep (60);
	} else {
	   /* This is the child process. Exit immediately. */
	   exit (EXIT_SUCCESS);
	}
	return 0;
}</pre>
<p>编译并运行这个程序，在程序运行期间，利用ps查看它的状态，你会得到下面的结果：<br />
<code><br />
$ ps -e -o pid,stat,cmd | grep zombie<br />
4302 S+   ./zombie<br />
4303 Z+   [zombie]<br />
</code><br />
你会发现进程4302——也就是僵尸的父进程——还没有结束，而进程4303进程的状态已经变成了“Z”。这也就意味这该程序产生的子进程已经变成了僵尸。</p>
<p>在一般的桌面系统上，即使产生僵尸进程也不是什么大不了的事情，因为，系统资源并不紧张的情况下，僵尸最终会被init清理。但是，在高负载的服务器或者资源非常有限的嵌入式系统中如果大量出现僵尸，那会是个一个麻烦。所以，避免产生僵尸进程的方法就是在父进程中正确的处理wait和SIGCHLD信号，具体做法google一下可以出很多结果，这里就不再累述了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/599/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在Ubuntu系统中使用KVM体验moblin</title>
		<link>http://www.adamjiang.com/archives/541</link>
		<comments>http://www.adamjiang.com/archives/541#comments</comments>
		<pubDate>Mon, 25 May 2009 15:54:35 +0000</pubDate>
		<dc:creator>jcadam</dc:creator>
				<category><![CDATA[Linux tips]]></category>
		<category><![CDATA[Intel]]></category>
		<category><![CDATA[KVM]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[moblin]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.adamjiang.com/archives/541</guid>
		<description><![CDATA[使用KVM体验moblin 系统要求 1. VT技术的CPU 你可以用下面的命令检查你的CPU是否支持VT技术。 $ egrep '(vmx&#124;smx)' /proc/cpuinfo 如果输出中出现flags:&#8230;云云，那么恭喜你，你很会买东西。 2. Ubuntu 9.04操作系统 请确认你的操作系统运行官方支持的内核，目前的版本是： $ uname -r 2.6.28-11-generic 需要的软件包 KVM和QEMU。 $ sudo apt-get install kvm qemu 启用VT技术 使用modprobe载入kvm相关的内核模块。 $ modprobe kvm $ modprobe kvm_intel 或者 $ modprobe kvm_amd 如果你得到如下的错误，说明你需要在BIOS设置中启用VT技术。 FATAL: Error inserting kvm_intel...Operation not supported. 如果已经用上面的方法确认了CPU是支持VT技术的，那么，说明在BIOS中VT并没有被启用。看看吧，浪费东西了吧。这说明使用Windows的很多用户都在浪费机器的性能。如果正是这样，请重新启动计算机，进入BIOS设置，在CPU相关选项中启用VT技术。 下载Moblin的KVM镜像文件 文件夹 http://repo.moblin.org/moblin/releases/test/alpha1/images/ KVM镜像的地址是 http://repo.moblin.org/moblin/releases/test/alpha1/images/moblin-netbook-core-alpha1-kvm.tar.bz2 用wget直接下载。 $ wget http://repo.moblin.org/moblin/releases/test/alpha1/images/moblin-netbook-core-alpha1-kvm.tar.bz2 [...]]]></description>
			<content:encoded><![CDATA[<p>使用KVM体验moblin</p>
<h3>系统要求</h3>
<p>1. <strong>VT技术的CPU</strong><br />
你可以用下面的命令检查你的CPU是否支持VT技术。<br />
<code>$ egrep '(vmx|smx)' /proc/cpuinfo<br />
</code>如果输出中出现flags:&#8230;云云，那么恭喜你，你很会买东西。</p>
<p>2. <strong>Ubuntu 9.04操作系统</strong><br />
请确认你的操作系统运行官方支持的内核，目前的版本是：<br />
<code>$ uname -r<br />
2.6.28-11-generic<br />
</code></p>
<h3>需要的软件包</h3>
<p>KVM和QEMU。<br />
<code><br />
$ sudo apt-get install kvm qemu<br />
</code></p>
<h3>启用VT技术</h3>
<p>使用modprobe载入<a href="http://www.linux-kvm.org/page/Main_Page">kvm</a>相关的内核模块。<br />
<code><br />
$ modprobe kvm<br />
$ modprobe kvm_intel<br />
或者<br />
$ modprobe kvm_amd<br />
</code><br />
如果你得到如下的错误，说明你需要在BIOS设置中启用VT技术。<br />
<code><br />
FATAL: Error inserting kvm_intel...Operation not supported.<br />
</code><br />
如果已经用上面的方法确认了CPU是支持VT技术的，那么，说明在BIOS中VT并没有被启用。看看吧，浪费东西了吧。这说明使用Windows的很多用户都在浪费机器的性能。如果正是这样，请重新启动计算机，进入BIOS设置，在CPU相关选项中启用VT技术。</p>
<h3>下载Moblin的KVM镜像文件</h3>
<p>文件夹<br />
<a href="http://repo.moblin.org/moblin/releases/test/alpha1/images/">http://repo.moblin.org/moblin/releases/test/alpha1/images/</a><br />
KVM镜像的地址是<br />
<a href="http://repo.moblin.org/moblin/releases/test/alpha1/images/moblin-netbook-core-alpha1-kvm.tar.bz2">http://repo.moblin.org/moblin/releases/test/alpha1/images/moblin-netbook-core-alpha1-kvm.tar.bz2</a><br />
用wget直接下载。<br />
<code><br />
$ wget http://repo.moblin.org/moblin/releases/test/alpha1/images/moblin-netbook-core-alpha1-kvm.tar.bz2<br />
</code><br />
解压，<br />
<code><br />
$ mkdir moblin-kvm<br />
$ tar jxf moblin-netbook-core-alpha1-kvm.tar.bz2 -C moblin-kvm/<br />
</code><br />
然后可以尝鲜啦。<br />
<code><br />
kvm moblin-netbook*.raw<br />
</code></p>
<p>当然，你可以尝试一下alpha2，镜像文件的下载地址如下：<br />
<a href="http://repo.moblin.org/moblin/releases/test/alpha2/images/">http://repo.moblin.org/moblin/releases/test/alpha2/images/</a><br />
已知问题可以参照Mobline V2的ReleaseNote。<br />
<a href="http://moblin.org/community/blogs/tshureih/2009/announcing-moblin-v2-core-alpha-release">http://moblin.org/community/blogs/tshureih/2009/announcing-moblin-v2-core-alpha-release</a></p>
<p>最后，一起欣赏一下桌面截图吧。<br />
<img src="http://lh5.ggpht.com/_O-FwCW3mN_w/Shq-3yUfuOI/AAAAAAAAENI/gxGu0V_q9uA/s400/Screenshot-QEMU.jpg" alt="moblin-run-in-KVM-ubuntu" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.adamjiang.com/archives/541/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

