2006年5月30日星期二

Private: 开放而且资源共享的p2p平台

据说微软在Vista中集成了p2p功能,这丝毫不奇怪,更不出人意料。2005年3月10日,微软买下了一家名叫Groove networks的公司,而这家公司的创始人Ray Ozzie则 成为了微软的CTO。Ray Ozzie何许人也,竟有如此能耐?大名鼎鼎的办公套件Lotus Notes的创始人是也。该牛人在1997年创立了Groove Networks,致力于新一代的协作办公套件的开发,而新一代协作办公套件的特点就是建立在P2P基础之上的虚拟办公环境(Virtual Office)。

P2P相对于传统C/S模式有非常多的好处,简单罗列之:

  1. 健壮

  2. 易于部署

  3. 成本低

  4. 由智能节点组成的P2P网络更适合建立起协作的应用环境,包括协同办公、在线游戏、流媒体播放等

  5. P2P这种分布式的智能网络能更有效的利用带宽(大家对P2P过分占带宽资源的认识,不能说是个误解,但也只能归咎于一些P2P实现的不合理)


微软买下Groove,自然是看中P2P在Office软件中巨大应用前景,而且我相信微软对P2P的应用远不止与此,很快就会推出基于P2P的游戏软件、通讯软件和多媒体软件。近年来,国内有很多公司进入P2P领域,微软涉足这一领域对这些公司将是很大的冲击。

我在03年攒毕业论文的时候,因为“研究”应用层组播的关系,看了些P2P的论文。当时就产生了一个想法,即搭建一个开放的、资源共享的P2P平台。简单 的想法就是,底层的P2P平台完成路由、寻址、会话功能;上层可以开发各种应用,包括协同办公、网络游戏、电话会议、内容共享等等。底层平台如同现在的 TCP/IP网络一样,是开放而且共享的。

在这个框架下,不论是skype、迅雷,还是电驴、BT,还是最近流行的P2P视频软件,都共享同一个P2P的平台,而不需要自己维护邻居信息、路由信 息。而很多聊天室(这个例子是不是有点无聊),联众的在线游戏,都不再需要高性能的服务器,而是通过P2P的方式来实现。

当时花了些时间考察Sun的JXTA,发现其不过本身不过是一个大而空的框架。本人对这种框架很反感,一上来就来个蒸汽锤(还不是实物,是个图纸),其实我只是需要一个改锥来钉个螺丝钉。

后来因为种种缘故,这个想法就一直放在那(一方面也实在是因为其工作量浩大,不是我等熬夜几个月能弄出来的)。但我始终认为这件事情很有意义,而且有其历史的必然性,即使不是我来做,也会有人做,而且会很快。
我想,也许用不了三年,就会有我今天所说的这种平台出现。空口无凭,撰blog为据。

架个wiki服务器,你用哪个软件?

以前用moinmoin架过wiki服务器,它 是用python写的。这次打算找一个php的wiki软件(毕竟php用得更广泛)。和往常一样,这次又面临选择,在debian下随便一找就发现了两 个php的wiki server,一个是mediawiki,另一个是phpwiki。值得一提的是wikipedia用的就是mediawiki,光凭这一点就足以说服我 用它了。在Debian下把这俩都装上试了试,从速度、配置方便性以及外观这几个方面,第一感觉wikipedia都做得好一些。
在网上搜了一下,有一篇文章很细的比较了三种wiki server。感兴趣的可以看一下。

2006年5月25日星期四

热核聚变还遥遥无期呀,wii便宜卖了

早上起来照例拿手机看看RSS,有篇新闻是说中国、欧盟、美国、俄国等几个大国/组织决定联合起来在法国建一座热核聚变反应堆,预计07年开工,将成为投入第二大的科技合作项目(第一大是啥?国际空间站?)。
文章最后说,如果一切顺利的话,到2040年有希望建成一座热核电站。看来想用上热核能源我还得注意点身体,多撑几年。

还有篇新闻挺鼓舞人心地,任天堂公布了他们的下一代游戏机wii在日本的发售价格,25000日元!算不上白菜价,但比PS3实惠多了。弄一个放卧室或者客厅还是蛮爽的,盛大的盒子得抓紧卖了,不然真拼不过人家啊。

2006年5月22日星期一

一部动画片的诞生,Elephants Dream

这部10分钟长的动画片最近很热,它并不是来自梦工厂、迪斯尼,而是几位艺术家在荷兰历时7个月制作的开源动画片。
开源动画片?这是头回听说吧。在软件业开源运动如火如荼的时候,艺术家同志们也不甘示弱,用开源的软件制作了这部开源的动画片,这部动画片的音轨、动画人物等所有素材都是开放的、免费使用的(可能也存在像GPL那样对用于商业目的的限制,这个不太清楚)。
粗看了一下这部动画片,欧洲风格十足,画面和音效都挺棒,不过情节没看很明白,挺灵异的反正。我想这部片子论证了这么两种可能:
1.利用开源的工具也能制作出优良的动画片
2.动画片也可以采用集市的方式来制作。

顺带提一下制作这部动画片所用到的开源软件(来自动画片的片尾):

  1. Blender,完成了这部电影的3D建模、动画制作、渲染和合成

  2. Gimp,类似photoshop的软件

  3. python,优秀的脚本语言

  4. twisted,如果没弄错的话,指的是python的twisted库,基于事件的网络程序框架

  5. OpenEXR,一种图片格式和相关的工具,

  6. KDE,两个最流行的开源桌面环境之一

  7. Verse,好像是在每次登录系统的时候显示一段圣经的软件,ft!

  8. Gnome,两个最流行的开源桌面环境之一

  9. CinePaint,以前叫做Film Gimp,顾名思义一把就是制作电影用的Gimp:)

  10. DrQueue,分布式渲染系统

  11. InkScape,制作svg的软件

  12. Subversion,版本管理软件

Linux需要微内核吗?

这个问题我回答不了。外面几个大佬还在为这事吵呢,其中有两个早几年就吵过一回,他们一个叫Linus,一个叫Andrew S.Tanenbaum。这两位大牛外加一位博士的文章如下,大家有兴趣的可以仔细看看:

泰老(Tanenbaum)在他文章的开头就强调:之所以再次挑起microkernel的事端,是因为时过境迁,系统稳定可靠正在成为超过系统性能的更重要的需求。泰老在文章中列举了4种提高系统稳定性和可靠性的技术,分别是:

  • Nooks: 目前是基于Linux的改进,特点是让驱动程序运行于沙箱之中,可以防止因为驱动程序bug导致的系统崩溃,可以恢复崩溃的驱动程序。因为驱动程序的代码 量占Linux内核代码的70%左右,并且代码质量低于其他部分代码,所以如果Nooks能达到其目标,整个系统的稳定性将会有很大的提高。

  • Paravirtual Machine:虚拟机(Virtual Machine)是最近比较火的技术(其实已经是非常老的技术了),相信很多人都玩过Vmware或者任天堂的模拟器,这些都算是虚拟机。虚拟机技术不光 是玩玩而已,它在降低企业的IT投入、提高稳定性和可维护性上都有重要的意义,Intel和AMD的新一代CPU中就会在指令级提供对虚拟技术的支持。 Paravirtual与一般虚拟机的不同在于,要对虚拟运行的系统做一定的修改。像UML(User mode linux)和Xen都算此类。泰老举的例子是L4,在L4上运行多个Linux系统,其中一部分专门运行驱动程序,一部分专门运行应用程序,哪个挂了都 不碍事。


按泰老所说,使用L4所带来的性能开销在3%到8%之间。这个数字跟Xen的性能相仿。

  • MULTISERVER OPERATING SYSTEMS:代表系统Minix3,也就是泰老自己设计的系统,典型的微内核设计,就不多说了。

  • 微 软的Singularity:来自微软的最激进的技术创新。在Singularity里,所有进程在同一个虚拟地址空间里运行,防止一个进程不适当的访问 另外一个进程的数据不是依靠硬件,而是依靠编译时的检查(这样上下文切换的开销就省掉了哦)。除了核心的部分代码由C#,C++和汇编写成外,其他部分都 是用一种被称为Sing#的类似C#的语言编写的。另外,在Singularity好像是采用了基于contract的开发。


在泰老发表了他的文章之后,Linus也毫不客气的再次把microkernel更稳定的论调称之为“crap“,不过不等泰老出招,一位从事微内核研究开发的博士就驳斥了Linus。具体如何大家看我在前文给出的链接。
孰是孰非,还是让我来说句公道话吧,Linus是一位技术天才,泰老则是学富五车著作等身的学术泰斗。从Linus的角度来说,他可能不太希望自己的系统 被翻天覆地的修改(每个做技术的人都有这种倾向,天才也不能幸免);而泰老当然看的更远。Linux的内核能在现有架构上支撑100年吗?显然不可能, 20年都难。总有一天,现在的Linux内核会以某种方式进入历史的回收站,而新的内核,可能已经不叫Linux了,将会建立在新的设计思路之上。
创新,永远都是一件好的事情。

Linux下清晰的中文字体

If 不想看我罗嗦 then goto HERE;

我终于在我的Linux下看到满意(基本)的中文显示了。
说来也是,用Linux这么多年(9年?),只在刚开始的时候倒腾过中文的显示,那时候上网不方便,电脑也很菜,很多技术不成熟,尝试一种方法,要先吭哧 吭哧下载半天,再吭哧吭哧编译半天,最惨的是,弄完后发现效果很差。难怪当年有人用了蓝点的中文Linux,号称流下了眼泪...
后来俺再也没在字体上多花过超过10分钟的时间。
转眼就跨了世纪,眼看第一个十年又过去一大半了,我琢磨着时代总该进步了,也该重新倒腾一下中文了。于是就在网上搜了搜。果然就有好的方法,果然就一试不爽。

HERE:
我找到的方法在这里:http://www.coolcode.cn/?p=55&pp=1
不过我在操作时后没那么麻烦,就下载了字体解压扔到/usr/share/fonts/truetype下,然后执行fc-cache(注,在哪个目录下执行这个命令都行),然后把local.conf拷贝到/etc/fonts/下。
因为我用的是kde,运行“kcmshell fonts“把字体设成Vera sans Yuanti就OK了。

用手机看rss,免费的哦

当然,你得用联通新时空。联通新时空收email是不要钱的(这年头不要钱的东西不多,不要钱的手机服务更少),拿你的手机信箱在rssfwd.com 这样的网站上注册一下,订阅你要看的RSS。这样一旦有新贴,rssfwd.com就会转发到你的手机上了。
以后上下班路上不会无聊了,小心别累着眼睛。

说道联通,有个有名的笑话是“孙子才用联通新时空”,可气的是作者在刚刚换到新时空的时候,老手机上收到高中同学(在移动工作)的短信,就是这个笑话。 我只好不动声色的发短信告知我的新号码。

大数运算,你用哪个库?

linux下有两个常见的大数运算库,libgmp和openssl所带的BN。它们的性能如何呢?作者写了两个小程序,分别利用这两个库,使用相同的RSA密钥(2048位),对相同的数据进行加/解密操作,用time比较性能,结果如下:

用私钥加密
gmp_imp: real 0m47.169s user 0m47.143s sys 0m0.004s
bn_imp: real 0m28.140s user 0m28.122s sys 0m0.004s
用公钥加密
gmp_imp: real 0m0.182s user 0m0.168s sys 0m0.000s
bn_imp: real 0m0.131s user 0m0.112s sys 0m0.000s

基本上,在使用私钥的时候,gmp的性能是openssl所带大数运算库的性能的60%。使用公钥时,性能差别不大,但gmp仍然慢于bn。
该测试是在debian unstable上完成的。

实战valgrind来优化程序

前一阵子写了一个gzip的解压程序,因为是用在嵌入式环境,而且是用于demo的目的,所以就一味的压缩空间,没有太多考虑优化性能。最终实现的程序目标代码8K左右,解压一个2M的gzip文件,我的程序myzip和系统自带的zcat性能如下:

myzip: real 0m0.439s user 0m0.408s sys 0m0.008s

zcat: real 0m0.195s user 0m0.148s sys 0m0.028s


myzip的性能瓶颈一个是读取bit流的函数,另一个是huffman解码。出于节省空间的考虑,huffman树的设计相当紧凑,解码性能的优化空间不大,于是想对第一个瓶颈做点工作。在优化开始之前,先用valgrind侦察一下敌情。


首先把程序用-g参数重新编译。然后先看看程序有没有什么bug,按如下方式运行:


$valgrind --tool=memcheck ./myzip file.gz


运行结束时,valgrind打印如下信息(stripped):

==5111== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)

==5111== malloc/free: in use at exit: 0 bytes in 0 blocks.

==5111== malloc/free: 537 allocs, 537 frees, 239,144 bytes allocated.


恩,看来内存操作方面没啥问题,那接着profile一下:


$valgrind --tool=cachegrind ./myzip file.gz


运行完毕后,valgrind打印出程序运行的一些统计信息,并在当前目录生成一个文件cachegrind.out.xxxx。(xxxx是4个“随机"数字)。虽然这个文件是human readable的,但是有更好的工具来看 -kcachegrind。


用kcachegrind打开这个文件,窗口显示如下:



果不其然,读取bit流的函数get_bits占用了66.37%的cycles,huffman解码函数get_code占用了14.75%。那下面就拿get_bits开刀。

$%#^*&^*&,搞定。


再profile一下,kcachegrind的截图如下:



get_bits的比例下降到45.78%,get_code上升到22.64%。

再用-O3编译的程序解压上面的压缩文件结果如下:

real 0m0.361s user 0m0.340s sys 0m0.004s


总结:

本文的情况是作者非常了解程序的瓶颈,在大部分情况下,这种信息并不明显(特别是如果程序不是自己写的)。通过valgrind的cachegrind功 能,可以直观的得到这些信息。这些定量的信息,对于优化程序很有帮助。即使是对于本文所列的情况,作者知道这两个瓶颈,但要分析出这两个瓶颈哪个更堵,以 及优化后可能达到的最佳效果,valgrind提供的信息仍然很有价值。


mono,kaffe和Novell

今早看rss feed,有下面几则新闻值得关注。
Miguel De Icaza访谈@osnews
此人是gnome的创始人,也是mono的创始人。作为微软.net技术的开源实现,mono很有希望获得更广泛的使用(比如Fedora Core5中加入了mono)。这篇访谈透露了一些mono的开发进展,比如定于4月发布beta1的mono1.2将提供Windows Forms的完整实现。
Kaffe1.1.7的性能评测
kaffe是一个开源的java虚拟机(jvm),开源世界一直试图实现一整套java开发运行环境。
对Novell的分析
Novell放弃Netware,彻底的转向了Linux。最近频频看到有关Novell、SLED10的新闻。SLED10(Suse Linux Enterprise Desktop)是Novell进军企业级桌面系统的武器。当然Novell决不是个一般的Linux公司,作为一个曾经辉煌过的大公司,Novell拥 有很多杀手级的企业应用软件,有大量在Netware时代积累下的用户关系。微软声称Novell转向Linux使得大量Netware用户转向 Windows,而Novell最近声称Vista的延期是SLED的机会。
顺便提一句,Miguel De Icaza受雇于Novell,Novell对mono的支持力度很大,所以微软和Novell的竞争可以说是相当直接。

让自己的驱动支持udev

从linux内核2.6的某个版本之后,devfs不复存在,udev成为devfs的替代。相比devfs,udev有很多优势,在此就不罗嗦了,提醒一点,udev是应用层的东东,不要试图在内核的配置选项里找到它;)
加入对udev的支持很简单,以作者所写的一个字符设备驱动为例,在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用class_device_create创建对应的设备。大致用法如下:

struct class *myclass = class_create(THIS_MODULE, "my_device_driver");
class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, "my_device");

这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件。

pc上最快的发包工具?

昨天做了个实验,测试了三种发包方式所能达到的最快速度。测试平台是一台双至强、1G内存的服务器,操作系统为Linux,内核版本2.6.15.3,网卡为Intel e1000光口网卡。使用一台smartbit来记录发包速度。
所使用的三种方法分别是:
tcpreplay:常用的发包软件,可以重发tcpdump所捕获的报文。
pktgen:linux内核自带的发包工具。
修改的e1000驱动:在驱动里直接写网卡的发送缓冲区
下面是测试结果:




























 tcpreplay ,64字节报文pkggen,64字节报文e1000,64字节报文tcpreplay,512字节报文pktgen,512字节报文e1000,512字节报文
pps298725600000610000232382234091234000
Mbps146266270908857850

说明一下,统计数据的值不算精确,因为只花了半个小时时间测了一下,但是拿来参考还是有说服力的。
可以看出,当发送小包时,tcpreplay的性能较差。发送大包时,三者性能接近。
有点出乎意料的是,通过e1000驱动发包,在64字节小包的时候也只达到不到300Mbps的速度。驱动修改的方式是在预先设置好e1000的4096个发送缓冲区,通过在中断处理函数里设置e1000的发送首尾指针来发包,相信这种方式是软件所能做到的最快的方式了。
如果继续深入测试,可以通过调整控制e1000中断产生的几个参数看能不能达到更高的吞吐率。但也可能e1000发包的上限就是这样了。

在ps3上跑linux…

今天看到的好消息,SONY已确认PS3将推迟发布,硬盘将成为PS3的标配,并且预装Linux。
我看不管是盛大的盒子,还是微软的Media Center,都不如这招狠,强劲的主机加上无限生命力的软件,套用一句广告,真是“nothing is impossible"。
不过我现在最想用我的手柄控制我的电脑(Linux系统),完成上网看新闻之类的简单工作。

GTK+编程FAQ之一

开场白:

GTK+是非常流行的GUI库,可以运行在Windows, XWindow(各种Unix环境),Framebuffer(各种嵌入式设备)和MacOS之上。很长时间以来,我用GTK+写一些简单的程序,所用语 言一般是c++或python,但我一直没有系统的看过GTK+的文档,所以有时候想实现一些功能却不知如何做。相信很多使用GTK+的朋友也遇到过类似 的情况,当然这些问题大多并不难,如果细细找一下文档,一般都能很快找到答案。
从本文开始,我将记录这些问题,希望能节省各位的时间,对各位有所帮助。
问题1:我想用GTK+,但是我不喜欢用C来写GUI程序,没有别的选择吗?

GTK+有很多语言的binding,除了使用各种脚本语言外,你还可以使用它的C++ Binding,gtkmm。实际上本文作者也非常讨厌用c来写gtk+程序,强烈推荐使用gtkmm。
问题2:如何提高编译的速度,特别是在使用gtkmm的时候?

这个问题并不局限于gtk+的开发,很多人抱怨gcc的编译速度,实际上使用预编译头文件可以大大提高编译速度。见作者《使用预编译头文件大大提高g++编译速度》一文。
问题3:没有可视化的界面设计工具吗?

glade是gtk+的可视化界面设计工具,它生成的glade文件是界面信息的xml描述。程序通过glade库加载xml文件就能声称界面。
问题4:如何产生异形的窗口(非矩形窗口)?

使用gtk_widget_shape_combine_mask函数来指定一个widget要显示的区域。
区域是由一个GdkBitmap定义,可以用gimp绘制你所需的形状,存成xdm图形文件,然后直接在源程序里include该文件,用gdk_bitmap_create_from_data来生成对应的GdkBitmap。
问题5:如何在系统托盘里放置图标?

问题6:如何设置主题?

问题7:如何使窗口没有title bar,不出现在任务栏里?

在XWindow下,窗口的title bar(包括最大化最小化按钮等等)是由窗口管理器(window manger,wm)负责绘制的。如果你不想让wm多管闲事,可以使用gtk_window_set_decorated(false)来通知wm。
同样,使用gtk_window_set_skip_taskbar_hint(false),你的窗口就不会出现在任务栏里了。
你也可以在使用glade创建界面文件的时候指定窗口的这些属性。
问题8:如何使用Gtk on framebuf

即将发布的2.10版gtk+带有对framebuf的支持(此前的版本需要额外的补丁)。
Debian SID的用户可以直接安装libgtk+2.0-directfb-dev这个包。

Linux下如何把IO空间映射到用户进程空间?

其实是个蛮简单的问题。在LDD3的第15章上有写(见“Remapping Specific I/O Regions”这一节)。不过当时作者选择了一个错误的做法:先把这块IO空间用ioremap映射到了内核空间,然后在用户进程访问被映射的地址所产 生的缺页中断里,用vmalloc_to_page得到page,返回给用户进程。
然而,vmalloc_to_page没法用在ioremap所得到的地址上,因为IO空间根本就没有对应的Page结构,返回的page指针自然是不对的。
正确的做法是在mmap函数里,使用remap_pfn_range函数。代码如下。注意要设置一下vma->vm_pgoff为你要map的io空间的物理地址对应的页。

static int filter_mmap(struct file *filp, struct vm_area_struct *vma)
{
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_pgoff = ( (u32)map_start >> PAGE_SHIFT);

if (remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
vma->vm_end-vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
return 0;
}

继续讨论van的channel

目前有三处相关的信息,一个是Van自己的presentation,在lwn上一篇比较深入的文章,另外还有一个blog讨论了这个问题。
Van的channel在提高linux TCP/IP协议栈的性能方面做了这样的工作:打破传统分层的TCP/IP设计架构,将IP包直接送达至目的地,好象是一条快速通道,Channel因此 而得名(但据lwn说,channel是指一种设计良好的环形buf,对它的读写不需要锁,而且对Cache非常友好,这么说也有道理,显然这么一种 buf是这个新框架所必须的)。这么做消除了多种开销,包括:

  • 当channel在应用层实现时,数据包从内核空间到用户空间的拷贝不再需要,而是通过内存映射将内核收到的数据直接映射到应用程序的地址空间。(这个buf的实现很有点意思)

  • 当channel在驱动实现时,不再需要skbuf(文物啊)来保存收到的报文,而是直接把报文丢到一个channel(一个环行buf)里。

  • 各种运行环境切换的开销(硬中断、软中断、系统调用)

  • Cache不命中的概率大幅降低,对smp更加友好


还有一点是不太明显的。有个“端到端原则”这样说道:要尽量把工作在网络的边界完成,网络本身只做尽可能少的工作。TCP就是这个原则的体现,可靠传输、流量控制、拥塞控制由连接的两个端点完成,网络只负责传输包,仅此而已。
但是诸位可能没注意到,我们目前的tcp协议栈并没有彻底贯彻这一原则,数据包被交给了协议栈,而不是交给了需要该数据包的程序,而这个程序才是真正的边 界。由于协议栈的处理所引入的包括延迟、丢包等情况使得应用程序无法看到真实的网络状况,这将导致无法有效的实施控制。比如TCP协议对RRT的计算会因 为报文在协议栈各层的排队、softirq的延迟而失真,会导致TCP吞吐量的下降。所以当Channel把报文直接送到应用程序时,才有可能实现高性能 的网络协议。

请注意有趣的一点,当channel一直通到应用程序时,需要在应用层实现TCP协议。

Channel对传统TCP协议栈性能的提升是巨大的,但同时对框架的改动也是根本性的,一些依赖于传统架构的应用不得不改写,包括被广泛使用的netfilter。
还有一个问题,就目前Channel的信息被遮遮掩掩的情况来看,这东西的license肯定有问题。而lwn上也有人向Van证实了这一点。 Channelized Driver和Channelized socket都会以GPL形式开放出来,但是channelized Application所需要的应用层TCP协议栈却由于某种原因无法GPL之。

valgrind,好东西,一般人我不告诉他~~

今天dot.kde登了一篇对valgrind的作者 Jonathan Riddell 访谈。我作为valgrind的老用户,当年调程序时获益很多,在这篇访谈里进一步长了见识,深感有必要把这个优秀的开发工具介绍给诸位。以下内容多翻译自该访谈(意译啦)。

啥是valgrind


Valgrind是帮助程序员寻找程序里的bug和改进程序性能的工具。程序通过valgrind运行时,valgrind收集各种有用的信息,通过这些信息可以找到程序中潜在的bug和性能瓶颈。
Valgrind现在提供多个工具,其中最重要的是Memcheck,Cachegrind,Massif和Callgrind。

Memcheck:


这个工具可以用来寻找c、c++和fortran程序中内存管理的错误。写c或c++程序时,很多隐藏很深的bug是内存操作上出了问题。而这些在 Memcheck面前都无处遁形(偶当年用的就是这个功能)。Memcheck可以检查出下列几种内存操作上的错误(大家自查一下有没有犯过;):

  • 读写已经释放的内存

  • 读写内存块越界(从前或者从后)

  • 使用还未初始化的变量

  • 将无意义的参数传递给系统调用

  • 内存泄漏

  • (笔者补充一条,同一个malloc的内存块释放多次。当年这么个bug让我找翻天)


Cachegrind:


这个工具可以提供详尽的profiling信息。它不光对指令、内存访问进行计数,更能针对每条指令、每行源代码、每个函数和每个程序统计cache的不 命中次数。大家应该知道,cache对目前系统的性能有决定性的影响。因此这些信息可以指导程序员调整代码,最大限度的提高程序性能。
访谈中提到,valgrind自身利用该工具在过去几个月内使性能提高了25%-30%。据早先报道,kde的开发team也对valgrind在提高kde性能方面的帮助表示感谢。

Massif:


Massif对内存的分配和释放做profile。程序开发者通过它可以深入了解程序的内存使用行为,从而对内存使用进行优化。这个功能对C++尤其有用(因为C++有很多隐藏的内存分配和释放)。

Callgrind:


Callgrind是一个复杂的工具(复杂到笔者没看太明白有关它的介绍)。它基于Cachegrind,除了具有Cachegrind的功能外,还可以统计调用带来的开销。

用法:


Valgrind使用起来非常简单,你甚至不需要重新编译你的程序就可以用它。当然如果要达到最好的效果,获得最准确的信息,还是需要按要求重新编译一下的。比如在使用memcheck的时候,最好关闭优化选项。



linux下的widget - Superkaramba

晚上花了点时间在Debian下尝试了一下superkaramba,安装完后运行出现窗口如下图(第一次运行只有两个选项,每安装一个“宝物”就会增加一个对应选项)。



选择“新建宝物”的选项,出现另一个窗口,在这个窗口里,你可以看到最新、最热门和下载次数最多的宝物排名,选中一项可以获得预览和简要介绍,点击安装即 可下载安装(这种模式是kde3.x之后添加的一个很cool的feature,我以前只知道可以用来下载墙纸),



随便安装了几个,show下截图:

试用感觉:

总体上,宝物数量和质量还不够高。比如那个控制播放器的软件还不能正确显示中文目录(唉,这种问题在开源世界里太常见了),那个记事本做得也忒糙了。不过天气预报软件做得很好,动画特效都很cool,那个系统monitor也做得不错。

另外,种类也不够多,面向web的应用不多,比如blog、rss reader、p2p。感觉人气还不够高,推出这么多年了,不如firefox的插件那么热火,也许随着kde4的推出会有所改观,在kde4里, superkaramba会以plasma的面目重新夺取世人的注意力。


但是。。。

但是局限于kde的plasma并不是一个针对widget的好的解决方案。开源世界应该推出一个标准的widget接口,提供诸如网络、 html/xml渲染、多媒体等功能,利用该接口写的widget可以无缝的运行于gnome、kde、xfce、fvwm等众多的窗口管理器/桌面环境 之中,甚至运行于windows上也不是不可能。


yahoo的widget

今天装了yahoo的widget,嗯,很华丽也比较实用。所谓widget就是一些完成特定功能的小窗口,象下面的抓图里就有Rss Reader,Clock,yahoo信箱监视器,天气预报,相册,yahoo信箱的地址本,搜索窗口等等。还可以从网上下载其他各种各样的 widget。

这一阵子流行web2.0,流行RIA(rich internet application),很多RIA还需要寄生在浏览器的窗口里,并不见得方便。用widget就摆脱了这个限制。当然基于浏览器的RIA也有其优势,比如易于部署之类。
开源世界也有类似的东东。KDE下很早就有一个很cool的软件叫superkaramba,能实现类似的功能,可惜一直没有被广泛的使用。如今 superkaramba改头换面叫做plasma,成为即将发布的kde4.0的重要组成部分。kde4.0计划在今年底或明年初发布beta版,相信 届时必然是很轰动的。

zim, 桌面wiki

zim是一个桌面wiki软件,我现在拿它来做工作记录,因为它秉承了wiki的特点,可以很容易的创建page,并且把page关联起来,所以用起来感觉条理很清晰。虽然现在还做得有点粗糙,但是已经足够用了,推荐之。
zim用的是GTK,不知道有没有被port到Windows上。
另:
有兴趣的朋友可以把zim改进一下,比如可以和web服务器同步,增加模板,增加协作功能。

Van Jacobson的Channel

Van Jacobson何许人也?Cisco的前任首席科学家,因为发明了TCP的慢启动和拥塞控制机制而被称作“拯救Internet的人”。最近Van又有 动作,这次不是对TCP协议本身的改进,而是对TCP/IP协议栈实现的优化,这个从架构上对TCP/IP实现所做的修改被称作Channel。
目前能找到的第一手资料只有Van在Linux.conf.au 2006上对此所做的Presentation。Van在Linux上实现了他的Channel,测试表明性能取得了惊人的提升。下表是从该Presentation中摘出的测试结果。

Van的测试环境是两台采用双至强2.4GCPU的Dell服务器,通过两块e1000网卡直接连接,操作系统是Linux,内核为2.6.15,e1000驱动版本为6.3.9。测试软件用的是netperf。
“1CPU”表示启用了CPU Affinity,“2CPU”表示未启用CPU Affinity,“drvr”表示采用了修改后的网卡驱动,即“Channelized Driver”,“sock”表示采用了“channelized socket”,“App”表示采用了“Channelized app”。“Busy”是CPU占用率,“Intr”和“Softint”是中断和软中断发生次数,
“Socket”、“Locks”、"Sched"和“App”代表相应的CPU占用率。
从此表可以看出,2CPU的性能要远小于2 x 1CPU,由于cache对系统性能的影响越来越大,增加CPU所带来的Cache开销会大大抵消新加CPU所提供的计算能力。通过采用 channelized driver可以很大程度的消除这种影响。随着对Socket和App的进一步优化,性能进一步提升,对比1CPU,2CPU和APP的数据,其结果是惊 人的。
可惜Van的Presentation里没有更多介绍改进的细节,我将在另外一篇blog里与大家讨论这个问题。

TCP协议各种变体的简介

&lt;!-- @page { size: 21cm 29.7cm; margin: 2cm } P { margin-bottom: 0.21cm } H1 { margin-bottom: 0.21cm } H1.western { font-family: "Nimbus Sans L", "Arial", sans-serif; font-size: 16pt } H1.cjk { font-family: "Tahoma"; font-size: 16pt } H1.ctl { font-family: "Tahoma"; font-size: 16pt } H2 { margin-bottom: 0.21cm } H2.western { font-family: "Nimbus Sans L", "Arial", sans-serif; font-size: 14pt; font-style: italic } H2.cjk { font-size: 14pt; font-style: italic } H2.ctl { font-size: 14pt; font-style: italic } --&gt; </p><br /><h2><font face="Nimbus Sans L, Arial, sans-serif"><strong><em><font size="4"><font color="#000000">前言:</font></font></em></strong></font></h2><br /><h2><font face="Nimbus Sans L, Arial, sans-serif"><strong><em></em></strong></font></h2><br /><p><font face="Nimbus Sans L, Arial, sans-serif"><em><font size="4"><font color="#000000"> </font></font></em><font size="3"><font color="#000000">tcp协议有非常多的变体。产生这些变体的原因在于网络传输中的拥塞控制是个非常复杂也非常重要的问题,特别是在高速高延迟的网络中,这个问题犹为重要。目前也不存在一个完美的解决办法。<br /><br /></font></font></font></p><br /><h2><font face="Nimbus Sans L, Arial, sans-serif"><font size="3"></font><strong><em><font size="4"><font color="#000000">Tahoe:</font></font></em></strong></font></h2><br /><p><font size="3" face="SimSun">慢启动,基于丢包的拥塞避免和快速重传,</font><font size="3" face="SimSun">Tahoe采用的这些拥塞控制算法为其他各种TCP所采用。对于传统低速而稳定的网络(局域网)而言,</font><font size="3" face="SimSun">Tahoe的性能是可以接受的。</font><font size="3" face="SimSun" /></p><br /><h2><font size="3" face="SimSun"><font face="Nimbus Sans L, Arial, sans-serif"><strong><em><font size="4"><font color="#000000">Reno:</font></font></em></strong></font></font></h2><br /><p><font size="3" face="SimSun"><font face="SimSun"><font size="3"> Tahoe对丢包非常敏感,1%的丢包率会导致</font></font><font face="SimSun"><font size="3">吞吐率降低</font></font><font face="SimSun"><font size="3">50%-%75。Reno</font><font size="3">在Tahoe基础上增加了快速恢复,可以一定程度上缓解这一问题。</font><br /><br /></font></font></p><br /><h2><font size="3" face="SimSun"><font face="Nimbus Sans L, Arial, sans-serif"><strong><em><font size="4"><font color="#000000">NewReno:</font></font></em></strong></font></font></h2><br /><p><font size="3" face="SimSun"><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun"> Reno</font></font><font size="3"><font face="SimSun">的快速恢复算法在“快速恢复”了第一个丢失的</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">segment</font></font><font size="3"><font face="SimSun">,即收到一个非重复、有效的</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">ack</font></font><font size="3"><font face="SimSun">之后就退出了快速恢复。这样当同一个窗口中有多个</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">segment</font></font><font size="3"><font face="SimSun">丢失时,</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">该算法只能对第一个丢失的包进行快速恢复,导致</font></font><font size="3"><font face="SimSun">性能降低。</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Newreno</font></font><font size="3"><font face="SimSun">的快速恢复算法做了小小的改进:在收到非重复、有效的</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">ack</font></font><font size="3"><font face="SimSun">之后,只有这个</font></font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">ack</font></font><font size="3"><font face="SimSun">对发生丢包的窗口内的所有数据做了确认,才退出快速恢复算法。</font></font></font></p><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"> 这种改进进一步增强了TCP的抗丢包能力。</font></font></font></p><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"><font size="2">注意:Reno和Newreno所做改进都是发生在发送端,对接收端透明。</font><br /><br /></font></font></font></p><br /><h2 align="left"><font size="3" face="SimSun"><font color="#000000"><font face="Nimbus Sans L, Arial, sans-serif"><font size="4"><em><strong>SACK:</strong></em></font></font></font></font></h2><br /><p><font size="3" face="SimSun"><font size="3"> SACK(选择确认)是解决</font><font size="3">丢包导致吞吐率下降</font><font size="3">的另外一种方法。在以往的确认方式(累积确认)下,接收方发回的ACK报文携带的信息量很少,使得发送方无法及时准确的得到报文丢失情况,从而无法准确及时的进行数据重传。而SACK的接收方的ACK报文带有更多信息。<br /><br />比如下面这种情况,发送方发出数据ABCDE,传输过程中B和D丢失,接收方只收到A、C和E。<br /><br />如果采用累积确认,接收方只能告诉发送方收到A,等收到发送方重传的B之后才能发送收到C的确认,再要等发送方重传D之后才能发送E的确认。<br /><br />如果采用SACK,接收方可以在第一条ACK报文里就告知发送方已经收到ACE,发送方直接重传B和D就行了。<br /><br />SACK要求接收方和发送方都支持SACK选项。目前主流的TCP协议栈都支持SACK。</font> <font face="Nimbus Roman No9 L, serif"><strong><em><font size="4"><font color="#000000"><br /><br /></font></font></em></strong></font></font></p><br /><h2 align="left"><font size="3" face="SimSun"><font color="#000000"><font face="Nimbus Sans L, Arial, sans-serif"><font size="4"><em><strong>HSTCP, STCP:</strong></em></font></font></font><font color="#000000"><font face="Nimbus Roman No9 L, serif"></font></font></font></h2><br /><p><font size="3" face="SimSun"><font size="3"> 都是Reno算法的变形。针对在大带宽高延迟链路情况下,通过提高拥塞避免阶段窗口增长的速度,减小丢包发生时拥塞窗口减小的速度,来提高吞吐率。<br /><br /></font></font></p><br /><h2><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><strong><em><font size="4"><font color="#000000">Vegas</font></font></em></strong></font><strong><em><font size="4"><font color="#000000"><font face="SimHei">:</font></font></font></em></strong></font></h2><br /><h2><font size="3" face="SimSun"><strong><em></em></strong></font></h2><br /><p><font size="3" face="SimSun"><font size="4"><font color="#000000"><font face="SimHei"> <font size="3"> Vegas对传统TCP做了相当大的改进,具体如下:</font></font></font></font></font></p><br /><ol><font size="3" face="SimSun"></p><br /><li><br /><p><font color="#000000"><font face="SimSun"><font size="3">更快速的重传</font></font></font></p><br /></li><br /><p></font></ol><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"><font color="#000000">为了避免对操作系统粗粒度时钟的依赖,</font></font></font></font><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Vegas</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">在每次重复的</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">ACK</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">到来时,都检查对应的</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">segment</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">是否已经可以超时重传。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"><font color="#000000">另外,发生重传时,如果重传的</font></font></font></font><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">segment</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">是在上一个大小的拥塞窗口下发送的,则不对拥塞窗口做减半操作。这么做可以避免拥塞窗口被过分减小导致传输性能下降。</font></font></font></font></p><br /><ol><font size="3" face="SimSun"></p><br /><li><br /><p><font color="#000000"><font face="SimSun"><font size="3">拥塞预测</font></font></font></p><br /></li><br /><p></font></ol><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"><font color="#000000">利用吞吐率的变化调整拥塞窗口,而不是利用丢包来检测拥塞。每收到一个有效的</font></font></font></font><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">ACK</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">,计算如下三个值:</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font color="#000000"><font face="SimSun"><font size="3"> Expected = WindowSize/BaseRTT</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font color="#000000"><font face="SimSun"><font size="3"> Actual = SentData/ActualRTT</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font face="SimSun"> <font size="3">Diff </font></font></font><font size="3" face="SimSun">= </font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Expected </font></font><font size="3" face="SimSun">- </font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Actual</font></font></font></p><br /><p><font size="3" face="SimSun"><font size="3" face="SimSun">其中,</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">BaseRTT</font></font><font size="3" face="SimSun">是该连接上观测到的最小的</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">RTT</font></font><font size="3" face="SimSun">值;</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">ActualRTT</font></font><font size="3" face="SimSun">是被确认</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">segment</font></font><font size="3" face="SimSun">被</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun"> </font></font><font size="3" face="SimSun">发送到收到</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">ACK</font></font><font size="3" face="SimSun">的时间间隔;</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">SentData</font></font><font size="3" face="SimSun">是</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">ActualRTT</font></font><font size="3" face="SimSun">内发送的数据量。</font></font></p><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Vegas</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">定义两个常量</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">a</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">,</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">b</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">(</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">a<b></font></font></font><font size="3"><font face="SimSun"><font color="#000000">,当</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Diff <a></font></font></font><font size="3"><font face="SimSun"><font color="#000000">时,则线性增加拥塞窗口;当</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Diff > b</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">时,线性减少拥塞窗口。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"><font color="#000000">这种拥塞控制方式是在拥塞将要发生时控制,而不是在拥塞发生后控制。正因为如此,Vegas的吞吐率不会象上面几种TCP,会有较大的波动。这种控制方式在高速高延迟的网络中,对性能的提升非常明显。<br /><br /></font></font></font></font></p><br /><ol><font size="3" face="SimSun"></p><br /><li><br /><p><font color="#000000"><font face="SimSun"><font size="3">慢启动的改进</font></font></font></p><br /></li><br /><p></font></ol><br /><p><font size="3" face="SimSun"><font color="#000000"><font face="SimSun"><font size="3">与拥塞预测的改进机制类似,通过监视吞吐率的变化来决定是否离开慢启动模式。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font color="#000000"> </font> </font></p><br /><p><font size="3" face="SimSun"> <font size="3" face="SimSun">通过以上三方面的改进,</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Vegas</font></font><font size="3" face="SimSun">可以提高带宽的利用率,减少重传次数,减少超时次数。这些改进主要针对大带宽高延迟的链路。</font></font></p><br /><h2><font size="3" face="SimSun"><font face="Nimbus Sans L, Arial, sans-serif"><strong><em><font size="4"><font color="#000000">Westwood</font></font></em></strong></font><strong><em><font size="4"><font color="#000000"><font face="SimHei">:</font></font></font></em></strong></font></h2><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000"> </font></font></font></font><font size="3"><font face="SimSun"><font color="#000000"> 在无线网络下,丢包通常是由于网络传输出错,而不是网络拥塞,造成的。传统</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">把丢包当作网络拥塞的标志而减小拥塞窗口,在这种情况下就会导致吞吐量的大幅下降。</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Westwood</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">通过持续测量连接的速度,在重传发生时,更“准确”的设置</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">ssthresh</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">和</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">cwnd</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">,从而改善了在无线网络下的吞吐率。</font></font></font></font></p><br /><h2><font size="3" face="SimSun"><font face="Nimbus Sans L, Arial, sans-serif"><strong><em><font size="4"><font color="#000000">Fast</font></font></em></strong></font><strong><em><font size="4"><font color="#000000"><font face="SimHei">:</font></font></font></em></strong></font></h2><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font face="SimSun"> <font size="3"> Fast“</font></font></font><font size="3" face="SimSun">似乎”是对</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Vegas</font></font><font size="3" face="SimSun">的进一步改进,它同样是利用网络延迟来推断网络拥塞。</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Fast</font></font><font size="3" face="SimSun">把</font><font size="3" face="Nimbus Roman No9 L, serif"><font face="SimSun">Reno</font></font><font size="3" face="SimSun">的问题归结如下:</font></font></p><br /><ol><font size="3" face="SimSun"></p><br /><li><font size="3"><font face="SimSun"><font color="#000000">拥塞控制阶段拥塞窗口增长过慢,减少过快,即</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">加法增长乘法减少AIMD</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">。</font></font></font></li><br /><li><font color="#000000"><font face="SimSun"><font size="3">丢包导致拥塞窗口维持在较高数值上的概率非常低</font></font></font></li><br /><li><font color="#000000"><font face="SimSun"><font size="3">拥塞窗口的大小无法稳定在合适的值上,而是上下波动。</font></font></font></li><br /><p></font></ol><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000"> Fast</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的拥塞避免算法基于一系列数学计算公式。一个公式给出TCP传输的平衡点,另外一个公式给出当前状态远离平衡点的距离。拥塞控制的目标是使传输状态逼近平衡点,在平衡点上,</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">达到链路所能稳定支持的最大吞吐量(即不往路由器队列中增加包的最大吞吐量)。它利用当前状态远离平衡点的距离大小来决定调整的方向和幅度。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000"> Fast</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的另一个特点是采用</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">。</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的采用是有争议的,早期的观点认为采用</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">并不会提高</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">传输效率,相反,会降低吞吐率。其原因简单的说是因为</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">导致路由器的队列里均匀分布着来自多个</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">连结的数据包,当队列满时,会导致多个</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">连接丢包,进而引起吞吐率的下降。</font></font></font></font></p><br /><p><font size="3" face="SimSun"> <font face="Nimbus Roman No9 L, serif"></font><font size="3"><font face="SimSun"><font color="#000000">但是对于</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Fast</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">这类采用基于延迟拥塞控制的</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">协议而言,它并不会在路由器的队列里塞过多的包,这样路由器上丢包的可能性会大大降低。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font size="3"><font face="SimSun"><font color="#000000"> 根据</font></font></font></font><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Fast</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的模拟结果,当网络中采用</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">从</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">0</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">增加到</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">100%</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">时,</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">和非</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的吞吐率都是单调增加的。并且在某个点上,所有</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">的吞吐率都高于未加入</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Pacing TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">之前的吞吐率。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000"> Fast</font></font></font></font><font size="3">在</font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">Sun的Solaris 10中被</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">采用,据评测是最快的</font></font></font><font face="Nimbus Roman No9 L, serif"><font size="3"><font face="SimSun"><font color="#000000">TCP</font></font></font></font><font size="3"><font face="SimSun"><font color="#000000">协议(跨洲际的大文件传输测试)。</font></font></font></font></p><br /><p><font size="3" face="SimSun"><br /><br /></font><br /></p><br /> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/tcp.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:41:00-07:00'>18:41</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/4616776742961587034' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BD%91%E7%BB%9C%E6%8A%80%E6%9C%AF' rel='tag'>网络技术</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=4616776742961587034&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='8720125954018813753'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/lexyaccc.html'>用lex/yacc分析c语言代码遇到的难题</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 最近在构思一个程序,对多个C源文件进行分析,找出各个变量、函数、结构、宏的定义和引用(跟sourceinsight差不多吧)。<br />从网上找到了c语言的lex/yacc解析器代码,但是这个代码在处理下面的代码时出错:<br />typedef unsigned char uint8_t;<br />uint8_t var;<br /><br />原因在于,当lex碰到uint8_t时,无法判定其是否为一个变量还是一个类型,只能把IDENTIFIER返回给yacc。而c的语法允许这样的语句:<br />some_var_or_type;<br />所以,不借助符号表,yacc无法判断其到底是变量还是类型。<br />先写到这,晚上看看文档,看看能不能解决。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/lexyaccc.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:40:00-07:00'>18:40</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/8720125954018813753' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=8720125954018813753&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='262146188910478963'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/libsigc.html'>用libsigc++实现信号机制 (旧文转贴)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 当年学微软的MFC时,被它用一大堆宏实现的事件处理机制困惑了很久;然后学习java,觉得java的事件处理机制不错,addlistener,多简 单多直观啊;再后来接触QT,用预处理的方式扩展c++的语义,实现了类似java的signal和slot机制,啧啧,也很清爽,就是稍微有点麻烦,而 且集成在qt内部,没法单独拿出来用,qt那么大一坨可不方便。<br />今天我要给大家介绍的这个东东就了不得了,它单单利用c++的泛型就实现了signal+slot的消息处理机制。虽然泛型颇让俺们这些c++菜鸟有点怕怕,但实际上这个库用起来简单到都快不值得写文档了。废话说这么多下面就介绍它是怎么用的。<br />比如偶有一个类,say,一个按钮Button吧。然后又有一个类叫MainFrame。我现在想让一个Button实例button被点击时 MainFrame实例mainFrame中的一个成员函数handleButton会被触发。我可以这样定义Button和MainFrame<br />class Button {<br />public:<br />....<br />sigc::signal clicked;<br />....<br />protected:<br />....<br />OnClicked(){ clicked.emit(this); }<br />};<br />class MainFrame{<br />public:<br />....<br />void handleButton(Button× pButton);<br />....<br />};<br /><br />然后在某处有类似这样的一段代码:<br />sigc::signal::iterator iter;<br />iter = button.clicked.connect(sigc::mem_fun(&mainFrame, &MainFrame::handleButton));<br /><br />这么一来,当button被点击时,mainFrame的handleButton函数就会被调用。如果有button1,button2,也可以这么联 结。这样mainFrame.handleButton就会处理多个Button的clicked事件,这时它可以通过pButton参数来判断到底是哪 个按钮被点击了。 而一个signal也可以同时联接到多个处理函数上。并且你还可以在运行中解除这种联结。上面代码中的iter就是干这个用的。<br />iter.disconnect();<br /><br />哇,怎么样,相当的灵活吧。能拿来做什么就看各位的想象力了,gtk的C++版本就是利用它实现的,见<a href="http://www.gtkmm.org/">gtkmm</a> 。<br />先就写这么多了,算是抛砖引玉,各位想用又有什么不明白就去看sigc++的文档好了。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/libsigc.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:39:00-07:00'>18:39</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/262146188910478963' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=262146188910478963&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='6890636526517330370'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/automakeautoconf.html'>使用automake和autoconf管理项目的上手指南(旧文转贴)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> <div><br /><div><br /><div><br /><div><br /><h1><a name="id2403732"></a>使用automake和autoconf管理项目的上手指南</h1><br /></div><br /><div><br /><div><br /><h3>Tiger Dong</h3><br /></div><br /></div><br /></div><br /><hr /></div><br /><div><strong>Table of Contents</strong> <dl> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2403464">前言</a></dt> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447288">automake和autoconf干吗使的</a></dt> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447336">Step by Step</a></dt> <dd> <dl> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447340">项目介绍</a></dt> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447373">先写Makefile.am</a></dt> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447444">生成configure.in</a></dt> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447528">大功告成</a></dt> </dl> </dd> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447541">补充问题</a></dt> <dd> <dl> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447546">使用预定义的宏</a></dt> <dt><a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#id2447652">如何为./configure增加参数</a></dt> </dl> </dd> </dl></div><br /><div><br /><div><br /><div><br /><div><br /><h2><a name="id2403464"></a>前言</h2><br /></div><br /></div><br /></div><br />本文肯定不是一个有关automake和autoconf的权威指南。如果你想找这种文档,可以参看<a href="http://sources.redhat.com/autobook/" target="_top">autobook</a>。 本文记录了作者在一个小程序中,用automake和autoconf管理项目的心得。因为作者也是初学乍练,所以本文既不能保证全面,也不能保证准确。 但是对新手而言,本文可以帮你避开冗长难懂的autobook(特别是对英文不好的朋友:),让你迅速上手,用automake和autoconf提高工 作效率,写出更好更规范的软件。</div><br /><div><br /><div><br /><div><br /><div><br /><h2><a name="id2447288"></a>automake和autoconf干吗使的</h2><br /></div><br /></div><br /></div><br />你编译过啥GNU的程序没?除了象mozilla, firefox, linux kernel或openoffice这些恐龙级的程序有自己一套代码编译发布系统外,大部分的GNU软件的源代码包都是用下面几步来编译安装的:<br /><div><br /><ol><br /> <li>执行./configure。这是一个shell脚本,它会很专业的检查系统环境,比如使用什么编译器,有没有哪个库之类,它还能带各种各样的参数,如果各项检查通过,它就会生成Makefile;</li><br /> <li>执行make进行编译;</li><br /> <li>make install。这就把编好的程序安装到系统里去了。</li><br /></ol><br /></div><br />很酷是吧?很专业是吧?这背后就是automake和autoconf的功劳。这套autotools工具大大减少了Makefile编写的工作量。下面就一步步的讲解它们的用法。</div><br /><div><br /><div><br /><div><br /><div><br /><h2><a name="id2447336"></a>Step by Step</h2><br /></div><br /></div><br /></div><br /><div><br /><div><br /><div><br /><div><br /><h3><a name="id2447340"></a>项目介绍</h3><br /></div><br /></div><br /></div><br />用来操刀演练的程序是作者写的一个小游戏(雏形),源文件大约10来个,还包括一些数据文件,主要是 一些图片。在<a href="http://www.idlecat.com/articles/Programming/runner.tar.bz2" target="_top">此处</a>可以下载。<br /><br />解开后的目录解构图如下所示:<br /><pre>/ --- src (保存源代码)<br />|<br />|_ gamedata (保存数据文件) ---- sprite (精灵动画) --- drop (往下掉的动画)<br />|_ left (往左跑的动画)<br />|_ right (往右跑的动画)<br />|_ stand (站着的动画)</pre><br /></div><br /><div><br /><div><br /><div><br /><div><br /><h3><a name="id2447373"></a>先写Makefile.am</h3><br /></div><br /></div><br /></div><br />除 了程序本身用到的文件,在每层目录下还有给automake使用的Makefile.am,Makefile.am是automake的输入,可以认为它 是更高层次的Makefile。坏消息是:这些Makefile.am你可得自己写,电脑不是你肚子里的蛔虫:)好消息是,写完这些就差不多大功告成了, 呵呵。<br /><br />根目录下的Makefile.am内容很简单,很明显就是告诉automake继续处理这两个子目录,以此类推,有子目录的目录中的Makefile.am都免不了这么一句。<br /><pre>SUBDIRS = src gamedata</pre><br />稍微复杂点的是$ROOT/gamedata/sprite/left下的Makefile.am,要告诉automake把数据文件装到哪:<br /><pre>EXTRA_DIST=1.bmp 2.bmp info<br />leftdir = $(datadir)/runner/sprite/left/<br />left_DATA = $(EXTRA_DIST)</pre><br />leftdir指明数据安装的路径,left_DATA指明要安装哪些数据文件。<br /><br />更复杂点的呢是$ROOT/src下的Makefile.am:<br /><br /><a name="srcmfam"></a><br /><pre>INCLUDES = -I/usr/include/SDL -D_REENTRANT -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include<br />bin_PROGRAMS = runner<br />runner_SOURCES =<br />ai.cpp animation.cpp anisprite.cpp gamestage.cpp gamesys.cpp<br />main.cpp sprite.cpp spriteone.cpp stagetwo.cpp<br />ai.h animation.h anisprite.h common.h gamestage.h gamesys.h sprite.h spriteone.h stagetwo.h<br />runner_LDFLAGS = -lSDL -lpthread -lsigc-2.0<br />AM_CPPFLAGS = -g -O0 -DDATADIR=\"$(datadir)\"</pre><br />这里用bin_PROGRAMS指定了最终要生成的可执行文件,用runner_SOURCES指定生成可执行文件runner需要的源文件。除此之外还有编译连接时的参数。大家可以看出,这其实就是Makefile的另外一种写法。</div><br /><div><br /><div><br /><div><br /><div><br /><h3><a name="id2447444"></a>生成configure.in</h3><br /></div><br /></div><br /></div><br />configure.in是autoconf的输入,autoconf的输出是configure脚本。<br /><br />笔 者开始傻傻的手写configure.in,后来才知道在$ROOT下执行一次autoscan就可以生成这个文件(叫configure.scan)。 autoscan会根据Makefile.am来生成configure.scan,所以在执行autoscan之前一定要先写好 Makefile.am,这样能省不少事哦。还有,debian下的autoscan运行时会报找不到configure.ac的错,其实不影响使用。<br /><br />自 动生成的configure.scan还需要修改才能用。前文说道,笔者是个菜鸟,因此别指望我把这个configure.in的用法解释得清清楚楚。不 过希望我说得够你用了:)下面就是修改前后的configure.in的对照,前面有-号表示要被删掉的行,+号表示增加的行,中文的注释是偶写的。<br /><pre>AC_PREREQ(2.59)<br />-AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)<br />+AC_INIT(runner, 0.1, idlecat511@yahoo.com.cn)<br />#下面这句一定要加<br />+AM_INIT_AUTOMAKE(runner, 1.0)<br />AC_CONFIG_SRCDIR([src/ai.cpp])<br />#config.h我还没研究,只好把它注释掉先。<br />-AC_CONFIG_HEADER([config.h])<br /><br /># Checks for programs.<br />AC_PROG_CXX<br />AC_PROG_CC<br /><br /># Checks for libraries.<br /># FIXME: Replace `main' with a function in `-lSDL':<br /># 注意这里,autoscan在src/Makefile.am中找到-lSDL这个选项,然后生成了下面这个语句来测试<br /># SDL的可用性。不过它不知道SDL里面有啥函数,所以要你手工把main换成SDL里的一个函数<br />-AC_CHECK_LIB([SDL], [main])<br />+AC_CHECK_LIB([SDL], [SDL_Init])<br /># FIXME: Replace `main' with a function in `-lpthread':<br /># 同SDL,奇怪的是,-lsigc-2.0为什么没有对应的项?<br />-AC_CHECK_LIB([pthread], [main])<br />+AC_CHECK_LIB([pthread], [pthread_create])<br /><br /># Checks for header files.<br />AC_HEADER_STDC<br />AC_CHECK_HEADERS([stdlib.h])<br /><br /># Checks for typedefs, structures, and compiler characteristics.<br />AC_HEADER_STDBOOL<br />AC_C_CONST<br /><br /># Checks for library functions.<br /># 因为源代码里调用了floor函数,autoscan就生成了这项,看起来autoscan做的工作不少啊!<br />AC_CHECK_FUNCS([floor])<br /><br />AC_CONFIG_FILES([Makefile<br />gamedata/Makefile<br />gamedata/sprite/Makefile<br />gamedata/sprite/drop/Makefile<br />gamedata/sprite/left/Makefile<br />gamedata/sprite/right/Makefile<br />gamedata/sprite/stand/Makefile<br />src/Makefile])<br />AC_OUTPUT</pre><br /></div><br /><div><br /><div><br /><div><br /><div><br /><h3><a name="id2447528"></a>大功告成</h3><br /></div><br /></div><br /></div><br />到这就算完了,剩下你要做的就是执行:aclocal;autoconf;automake --add-missing。这样你就会发现目录下面多了好多文件,其中就有你日思夜想的configure。</div><br /></div><br /><div><br /><div><br /><div><br /><div><br /><h2><a name="id2447541"></a>补充问题</h2><br /></div><br /></div><br /></div><br /><div><br /><div><br /><div><br /><div><br /><h3><a name="id2447546"></a>使用预定义的宏</h3><br /></div><br /></div><br /></div><br />在正文的例子中,我在前面的<a href="http://blog.donews.com/fckeditor/editor/fckeditorarea.html#srcmfam">src/Makefile.am</a> 里写死了SDL和sigc++这两个库的编译参数,包括CPPFLAGS、LDFLAGS。这么做其实有违auto工具的初衷,因为如果碰到的系统,它的 SDL和sigc++安装路径与Makefile.am所写不一致,程序就没法编译了。正确的作法是让configure脚本来检测这些参数。<br /><br />难道要自己写脚本?这又是件让很多人头大的事情。幸运的是autotools已经提供了很多宏帮助你完成大部分这类工作。正好SDL和libsig++代表了两种不同的情况,下面就继续拿正文中的例子做示范,来讲解宏的使用。<br /><br />先看看修改后的src/Makefile.am:<br /><pre>bin_PROGRAMS = runner<br />runner_SOURCES = ai.cpp animation.cpp anisprite.cpp gamestage.cpp gamesys.cpp<br />main.cpp sprite.cpp spriteone.cpp stagetwo.cpp<br />ai.h animation.h anisprite.h common.h gamestage.h gamesys.h sprite.h spriteone.h stagetwo.h<br />runner_LDADD = $(SDL_LIBS)<br />$(SIGCPP_LIBS)<br />AM_CPPFLAGS = -g -O0 -DDATADIR=\"$(datadir)\"<br />$(SDL_CFLAGS)<br />$(SIGCPP_CFLAGS)</pre><br />可以看到,所有写死的参数定义都被去掉了,增加的是四个变量:$SDL_LIBS, $SDL_CFLAGS, $SIGCPP_CFLAGS和$SIGCPP_LIBS。可是这四个变量是如何被正确赋值的呢?那就要在configure.in中做手脚了,下面是修 改后的configure.in文件:<br /><pre>AC_PREREQ(2.59)<br />AC_INIT(runner, 1.0, x@y.z)<br />AM_INIT_AUTOMAKE(runner, 1.0)<br />AC_CONFIG_SRCDIR([src/ai.cpp])<br />#AC_CONFIG_HEADER([config.h])<br /><br /># Checks for programs.<br />AC_PROG_CXX<br />AC_PROG_CC<br /><br /># Checks for header files.<br />AC_HEADER_STDC<br />AC_CHECK_HEADERS([stdlib.h])<br /><br /># Checks for typedefs, structures, and compiler characteristics.<br />AC_HEADER_STDBOOL<br />AC_C_CONST<br /><br /># Checks for library functions.<br />AC_CHECK_FUNCS([floor])<br /><br />AM_PATH_SDL(1.2.7,,AC_MSG_ERROR([<br />*** SDL 1.2.7 is required to build runner<br />]))<br /><br />PKG_CHECK_MODULES(SIGCPP, sigc++-2.0,, AC_MSG_ERROR([<br />*** sigc++-2.0 is required to build runner<br />]))<br />AC_SUBST(SIGCPP_CFLAGS)<br />AC_SUBST(SIGCPP_LIBS)<br /><br />AC_CONFIG_FILES([Makefile<br />gamedata/Makefile<br />gamedata/sprite/Makefile<br />gamedata/sprite/drop/Makefile<br />gamedata/sprite/left/Makefile<br />gamedata/sprite/right/Makefile<br />gamedata/sprite/stand/Makefile<br />src/Makefile])<br />AC_OUTPUT</pre><br />先看对SDL的处理,我们使用了一个宏AM_PATH_SDL,这个宏的定义在/usr/share/aclocal/sdl.m4中(这 个文件是包含在sdl的开发包中的,我使用的是Debian系统,可能在别的系统路径会有所不同)。这个宏展开后就是一段检测SDL库并设置$ SDL_LIBS, $SDL_CFLAGS的脚本,如果有兴趣可以查看一下./configure文件,看看这些宏展开后都生成了什么脚本。<br /><br />sigc++的情况跟SDL有所不同,在/usr/share/aclocal下并没有sigc++.m4文件。但是在 /usr/share/aclocal/pkg.m4中定义了宏PKG_CHECK_MODULES,用来处理所有可以用pkg-config处理的库。 这个宏和AM_PATH_SDL差不多方便,只不过要多两句AC_SUBST(SIGCPP_CFLAGS)和AC_SUBST (SIGCPP_LIBS),否则这两个值没法被传递到Makefile中去。</div><br /><div><br /><div><br /><div><br /><div><br /><h3><a name="id2447652"></a>如何为./configure增加参数</h3><br /></div><br /></div><br /></div><br />未完待续:)</div><br /></div><br /></div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/automakeautoconf.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:37:00-07:00'>18:37</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/6890636526517330370' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=6890636526517330370&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='784278252190265259'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/nstcp.html'>用ns模拟TCP,结果费解!</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> <p>ns的版本是2.29,打了fast tcp的补丁。模拟环境的设置很简单:两个节点,其间用20Mb,200ms的链路连接;在两个节点之间建一个tcp连接,应用层跑FTP,持续时间从0.5到600.5,测试结果如下图:<br /><br /><img src="http://static.flickr.com/37/87718026_1627fc0caa.jpg?v=0" /><br /><br />从图可见,Vegas经过将近400秒后稳定在20Mb,Tahoe和Newreno的峰值是20Mb,Tahoe围绕10Mb振荡,Newreno围绕15Mb振荡,而号称最快TCP的Fast速度始终没超过3Mb。<br /><br />不太理解的地方:</p><br /><ol><br /><li>Vegas、Newreno和Tahoe都需要相当长的时间(将近400秒)才能到达预期值</li><br /><li>Newreno和Tahoe的波动都非常利害</li><br /><li>Fast的模拟结果显然无法取信,应该是模拟软件编写的问题</li><br /></ol><br /> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/nstcp.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:36:00-07:00'>18:36</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/784278252190265259' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BD%91%E7%BB%9C%E6%8A%80%E6%9C%AF' rel='tag'>网络技术</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=784278252190265259&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='6073165824675141844'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/extensionfirefox.html'>用extension来武装你的firefox</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> firefox是个非常好用的浏览器,在这里可以<a href="http://www.mozilla.org/">下载</a>。Firefox不光是一个最符合w3c标准的浏览器,你还可以通过extension(翻译成“扩展”也许比较合适)机制让你的浏览器具有各种各样很cool的功能,下面是我常用的extension:<br /><ol><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=398&application=firefox">ForecastFox</a>: 在状态栏上显示天气预报,推荐</li><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=436">SessionSaver</a>: 记录当前你浏览的网页,甚至你正在填写的表格内容,下次启动浏览器就不用重新打开网页填写表格了,强烈推荐</li><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=173">GmailNotifier</a>:替你定时检查gmail信箱,推荐</li><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=77">Sage</a>:RSS阅览器,偶每天都用它来查看slashdot, lwn, linuxtody, osnews。强烈推荐</li><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=158">Tabbrowser Preferences</a>:改善firefox的tab功能,属于不可不装的</li><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=220">flashgot</a>:让firefox调用现有的下载工具,比如windows下的flashget,linux下的kget,来下载文件。不可不装。</li><br /> <li><a href="https://addons.mozilla.org/extensions/moreinfo.php?id=433">flashblock</a>:把网页中的flash显示为一个播放按钮,只有你点击才会下载并显示。强烈推荐</li><br /> <li><a href="https://addons.mozilla.org/firefox/2464/">FoxyProxy</a>:增强Firefox的代理配置功能,配合Tor使用非常好。<a href="http://my.donews.com/idlecat/wp-admin/tor.eff.org">Tor</a>是一个可以解决国内各种网络故障的神奇软件,比如前一阵子hotmail和gmail不好用,wikipedia访问不了等种种问题。</li><br /></ol> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/extensionfirefox.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:35:00-07:00'>18:35</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/6073165824675141844' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E4%BA%92%E8%81%94%E7%BD%91' rel='tag'>互联网</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=6073165824675141844&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='6909291438021333825'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/linux-network-performance-monitor2005.html'>linux network performance monitor(发表时间:2005-12-30)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 最近在想办法测试tcp协议栈性能,对一个tcp连接,能实时的获得它的吞吐率(吞吐率只是最基本的要求,还有更多的性能参数),而且不需要改变应用程序,并且开销较小。<br />一开始用iptables在应用层做,写了个demo。但是这种办法对性能上会有一定影响,而且iptables好像也无法区分重传的tcp包,而这些包是不能算进吞吐率的,这样就会导致结果不准确。<br />最终的想法是直接修改tcp协议栈,看起来net/ipv4/tcp_input.c:tcp_data_queue是tcp协议栈把有效的数据交给userspace的地方。这样我至少可以在接收方得到接收速率的采样。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/linux-network-performance-monitor2005.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:34:00-07:00'>18:34</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/6909291438021333825' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=6909291438021333825&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='3647198410742939159'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/lxr2005-12-29.html'>改进lxr的一些想法(发表时间:2005-12-29)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 最近一直在做linux内核上的开发,免不了要看大量的内核源码。所谓“工欲善其事,必先利其器”,要看像linux内核源码这么大规模的项目,自然得找 个好的看源码的工具。不过目前的工具都无法达到我的期望。我现在是用lxr看代码,如果能做如下增强就比较perfect了。<br /><ol><br /> <li>结合wiki,可以 添加注释。这个功能很有意义,说不定可以大幅度改善很多开源项目的文档状况。</li><br /> <li>现在的lxr,如果查找一个static的符号定义,仍然要调用了ident search功能,既影响用户浏览速度,也增加了服务器的负担。实际上在当前页面就能找到定义,根本不用跟lxr服务器交互。</li><br /> <li>在查看源码时,可以给出当前 源文件的符号列表,以便于快速浏览</li><br /></ol> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/lxr2005-12-29.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:34:00-07:00'>18:34</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/3647198410742939159' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=3647198410742939159&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='7642287065579802543'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/tcp2005-12-10.html'>tcp测试程序的进展(发表时间:2005-12-10)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 这几天把代码用svn管理起来,增加了建立并发连接的接口。定时器也加进去了。写了几个测试例,已经是非常的顺手。几十行代码就能完成对一个复杂场景的模拟。下一步除了修改bug,编写更多的测试例,再就是把测试结果自动分析加入进来。<br />不过拿pc来做网络测试设备,能力还是很有限。头一个局限就是普通pc抓包速度太慢了。现在看来超过2000个并发连接就会有问题,猜测是出现了丢包。所以后面的测试还是侧重于单连接吧。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/tcp2005-12-10.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:32:00-07:00'>18:32</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/7642287065579802543' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=7642287065579802543&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='8204667634405486115'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/blogspotmono2005-12-10.html'>很遗憾,blogspot又被政府封了,再谈mono(发表时间:2005-12-10)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 虽然还能在blogger上发贴,国内却无法看到,政府很为我等草民的隐私考虑啊!郁闷归郁闷,生活还要继续呀。在没找到新家之前,接着贴吧!<br />上 回说到.net和mono的好处,前几天在网上捕风捉影,firefox2.0的平台也有开发者在考虑用mono了。gnome肯定会在adopt mono上走在前面,现在firefox也有希望加入进来,真是个好消息。firefox在借鉴微软技术方面是有传统的,现在firefox用的 xpcom就是照搬微软的com技术。<br />不过kde比较悬,kde用的是qt,qt虽然是GPL的,但是它的开发主要是由 TrollTech这家公司做的。TrollTech的老总表态说,肯定会积极跟进.Net,但不会是在Linux平台。我虽然一直用kde,但是却在这 一点上觉得很不爽,要是kde也搬到gtk上就好了,gtk一统江湖,岂不乐哉! <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/blogspotmono2005-12-10.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:32:00-07:00'>18:32</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/8204667634405486115' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E4%BA%92%E8%81%94%E7%BD%91' rel='tag'>互联网</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=8204667634405486115&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='5987159757541037728'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/g2005-12-01.html'>预编译头文件大幅度提高g++的编译速度(发表时间:2005-12-01)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 今天晚上做了个实验,发现使用了预编译头文件之后,g++的编译速度有了质的飞跃。<br />用过Visual C++的朋友应该还记得有个叫stdafx.h的头文件是几乎每个vc程序都要包含的,这其实就是个预编译头文件(precompiled header)。今天就用同样的方法来提高g++编译的速度。<br />拿来试刀的是个很小的gtkmm程序test.cpp,长度67行,完成的功能就是加载一个glade的UI配置文件,然后处理几个按钮事件。别看它小,在我的牛机器上编译起来还真不快,肯定是预处理花了太多时间。看看它包含的头文件:<br />#include<br />#include<br /><br />#include<br />现在把这几行从test.cpp中拿出来放到一个单独的头文件common.h(与test.cpp在同一目录)中,并在test.cpp的开头加入#include ”common.h“,替换掉原先三个头文件包含。<br />下面成预编译头文件:<br />$g++ -c `pkg-config --cflags libglademm-2.4` common.h<br />是不是很奇怪,头文件也能拿来编译。编译完生成一个common.h.gch文件,这就是预编译的头文件了,看一下大小,哇塞,46兆。这会明白编译为啥慢了吧。<br />接着再编译test.cpp:<br />$g++ `pkg-config --cflags --libs libglademm-2.4` test.cpp<br />速度明显加快。空口无凭,数据为证,下面是使用预编译头文件前后的所需时间对比:<br />使用前:<br />real 0m1.552s<br />user 0m1.385s<br />sys 0m0.129s<br />使用后:<br />real 0m0.381s<br />user 0m0.279s<br />sys 0m0.070s<br />仅仅用了个预编译头文件,编译速度就提高了如此之多,真的好有效果耶~~~ <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/g2005-12-01.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:31:00-07:00'>18:31</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/5987159757541037728' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=5987159757541037728&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='5702095454464432664'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/net2005-11-30.html'>.net其实是个好技术(发表时间:2005-11-30)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 好象突然一下,全世界持各种语言的人就能无障碍的互相沟通了,各种语言的知识积累可以共享了。这所具有重要的意义,与开源运动的意义在一定程度上是吻合的;但另一方面也削弱了开源的必要性。<br />我承认,我做技术做得是有点偏执,虽然意识到.NET的好处,也决定学它一学,可还是打算先尝试一下开源的.NET实现:<a href="http://www.mono-project.com/Main_Page">mono</a>。试用了一下最新版的monodevelop(ver0.9),还不错;接着又试用了Visual Studio 2005 Express,也很不错。<br />请原谅我用这么笼统的评价,完全没有参考价值。问题是,一直用vi的话,对IDE的要求很低,好象能编辑就行了:) 对习惯用ide的人来说,monodevelop还缺一个集成的GUI设计器,可以用glade+gtk sharp顶一下;而VS2005当然是有的,而且还提供了那么多直 接可用的form,比VS5.0真是多多了。<br />有一点要承认,微软的编译器速度真是飞快...记得前一段时间有讨论说微软编译器这么快的原因之一是使用了预编译(precompile),gcc也可以采用同样的方法加速。有空的时候可以试试,现在编译c++程序,gcc真是太慢了:( <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/net2005-11-30.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:30:00-07:00'>18:30</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/5702095454464432664' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=5702095454464432664&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='1340690272679034417'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/gtktips2005-11-25.html'>GTK编程的TIPS(发表时间:2005-11-25)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> <ol><br /> <li>界面设计可以使用glade。glade提供可视化的界面编辑功能,结果被保存为一个xml文件(后缀为glade)。虽然glade还 可以生成代码框架。但是已经不建议使用(在新版本的glade中,代码生成功能将被废弃),而是由程序使用libglade库来读入xml文件。</li><br /> <li>除了可以用c来写GTK程序之外,还可以用c++,python等很多语言。</li><br /> <li>GTK的多国语言编程应使用gettext来完成</li><br /> <li>程序读入glade的xml文件时,可以部分读入。这意味着可以在一个glade文件里,描述很多个窗口,或者描述窗口的一部分。</li><br /></ol> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/gtktips2005-11-25.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:29:00-07:00'>18:29</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/1340690272679034417' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=1340690272679034417&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='5580458521418108798'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/private-python2005-11-24.html'>Private: python的多线程问题(发表时间:2005-11-24)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 最近用python写程序,实用多线程的时候遇到一个很奇怪的问题。程序的大致结构是主线程负责用户输入,另外两个线程一个主动发起TCP连接,另外一个在一个端口上监听TCP连接。<br />首先由于多线程的python程序只有主线程能收到signal,所以监听线程不能简单的阻塞在listen()上,否则就没法正常结束这个程序。因此监 听线程是在一个循环里调用设置有超时参数的select,这个循环的结束条件是一个Event实例被clear。clear操作是由主线程完成。<br />然而该程序却不能象预想的那样工作,主线程调用clear对监听线程不起作用!后来把程序简化到在循环体内只做打印、只import threading时,it works。但最奇怪的是,仅仅把import select加回去,就又不工作了。<br />该现象发生在python2.3上,windows版本和Debian上都验证过。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/private-python2005-11-24.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:29:00-07:00'>18:29</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/5580458521418108798' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=5580458521418108798&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='4657236262333625963'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/tcp2005-11-24_22.html'>在应用层写了个tcp实现雏形(发表时间:2005-11-24)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 在linux平台上做,发包利用rawsocket,收包用libipq(见<a href="http://www.netfilter.org/">www.netfilter.org</a>)。之所以不用rawsocket收包,是因为rawsocket在接收非icmp的报文时,对该报文进行了复制,也就是说如果是TCP报文的话,除了 rawsocket可以得到它,内核的tcp协议栈也能得到它,这样tcp协议栈会发出一些我们不想看到的rst报文。你得到它了吗?;)<br />这个小小的实现目前只能完成建立连接,断开连接、收发报文等功能,流量控制、拥塞控制都没有做。不过用来模拟各种TCP状态机的异常情况,发送病态报文,已经足够了。<br />为了使得模拟异常情况的代码容易编写,该实现在每个事件点(如收到报文、发送报文、超时)调用回调函数。也就是说模拟异常情况的代码只需要写回调函数并将其注册在合适的事件点上就可以了。在回调函数里可以修改TCP状态,修改报文或者干脆不让该报文被发送或接收。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/tcp2005-11-24_22.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:28:00-07:00'>18:28</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/4657236262333625963' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=4657236262333625963&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='697974015723633247'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/tcp2005-11-24.html'>tcp测试(发表时间:2005-11-24)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> tcp的测试蛮麻烦。目前设想了两种测试方法。一种是完全用rawsocket收包发包,相当于在应用层重新实现一套tcp协议。当然这么复杂的tcp协 议完全实现太没有必要了,所以这种方式只适合模拟一些简单的测试情况。比如TCP建立连接、断开连接时的各种情况、各种异常报文、边界条件。<br />另一种测试方法是利用操作系统自身的tcp,测试程序监视tcp连接,在适当的时候施加控制,甚至整个接管。<br />最后就是测试结果的分析,测试结果是测试过程中记录下来的tcp报文。分析程序据此判断被测tcp协议栈有没有正常的work。<br />分析这两种测试方法和最后的结果分析,它们公共的部分是实现tcp协议栈状态机,后面两个的状态机甚至比tcp本身状态机还要复杂,因为它们是被动的 监听者,简单的说,当一方报文到来时,它不能确定另一方是否进入某种状态,而是要等待其发出应答报文,这样状态数就扩大了。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/tcp2005-11-24.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:27:00-07:00'>18:27</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/697974015723633247' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=697974015723633247&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='445677663655354112'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/windowsgtk2005-11-23.html'>在windows上安装GTK运行/开发环境(发表时间:2005-11-23)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 其实是件很简单的事情。这里说的是一整套环境,包括gtk的运行环境和开发环境,gtkmm的运行和开发环境,和pygtk。<br />如果要做c语言的开发,装 gtk的开发环境就行;要是用C++,就要装gtkmm的开发环境;要是只用python,装pygtk就行了,当然要先装一个python for windows。<br />还有,做gtk的界面开发,glade当然是必不可少了。<br />gtk和glade的windows版本从<a href="http://gladewin32.sourceforge.net/">这里</a>可以下载。gtkmm和pygtk的window版本可以从<a href="http://www.pcpm.ucl.ac.be/%7Egustin/win32_ports/">这里 </a>下载。对了,gtkmm的安装程序会自动检查机上是否装有gtk,如果没有它会自动下载,如果网络环境好,这倒也很省事。<br />gtk的这一套开发环境应该是可以配合msvc工作的,不过我一向是用gcc的windows版本mingw,从这里可以下载:<a href="http://www.mingw.org/">www.mingw.org</a> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/windowsgtk2005-11-23.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:26:00-07:00'>18:26</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/445677663655354112' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B' rel='tag'>编程</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=445677663655354112&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='197774693014945186'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/tcprevisit2005-11-19.html'>TCP协议revisit(发表时间:2005-11-19)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 最近因为要测试公司的TCP协议栈,把TCP的几个主要RFC都翻来覆去的看了好几遍,以前网络课上对TCP的那点理解这回大大加深了一把。TCP这个协 议真是值得搞网络的人仔细读一读,现在p2p、流媒体什么的都很火,这些应用都免不了大量的数据传输。如何才能尽可能快速的传输数据,又不会导致网络的瘫 痪,都可以在TCP的协议设计中找到有价值的参考。<br />比方说,TCP协议是一个负责任的协议,是internet上的好公民。这话什么意思呢?如果 网络上的传输都可着劲的发,结果就会象上班高峰期的北京的十 字路口,大伙堵在那谁也动不了。TCP虽然尽可能的利用网络带宽,但也会根据网络的拥塞情况动态的调整自己的速度。这就是TCP的一个重要机制,拥塞避 免。在这一点上TCP真是做足了文章。可以说正因为如此,现在的internet才能承载我们每天所用的各种网络应用;另一方面,这可能也就是接入服务提 供商们封杀P2P下载的原因。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/tcprevisit2005-11-19.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:25:00-07:00'>18:25</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/197774693014945186' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E7%BD%91%E7%BB%9C%E6%8A%80%E6%9C%AF' rel='tag'>网络技术</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=197774693014945186&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='8368293865981983044'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/kde35-2005-11-19.html'>正在安装kde3.5(原发表时间 :2005-11-19)</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 昨天听说kde3.5-rc1进了debian的alioth.debian.org的repository。今天一回到家就开始dist- upgrade,歌华宽带倒也争气,正以~100KB/s的速度下载。想当年大四的时候赶上kde2.0发布,好象还不是正式版,不是beta就是rc, 下源代码下了一整夜。还得人盯着,下不动了就换代理。更别说到后来在偶的烂机器上编译那个费劲了。<br />五年后的今天,KDE3.5已经rc了,让人望眼欲穿的4.0也渐渐浮出水面,期待中...。<br /><br />我虽然一直用KDE,但在GUI开发上却倾向于使用gtk而不是KDE所用的QT。这一方面是因为qt的license问题,比如没有免费的 windows版(这个问题在即将到来的4.0中已经解决);另一方面,gtk的c++ binding,gtkmm做得也非常好。<br />早年不愿意用gtk的原因是因为它是基于c语言的,写起界面来特别罗嗦,而QT的signal/slot机制在当时看来非常棒。后来gtkmm出现了,它 用libsigc++库实现了更elegant的实现了signal/slot机制,一下子就俘虏了偶的心;) <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/kde35-2005-11-19.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:24:00-07:00'>18:24</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/8368293865981983044' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/Linux' rel='tag'>Linux</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=8368293865981983044&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry'> <a name='6970844728790285738'></a> <h3 class='post-title entry-title'> <a href='http://idlecat.blogspot.com/2006/05/blog-post.html'>再次搬家</a> </h3> <div class='post-header-line-1'></div> <div class='post-body entry-content'> 上次从blogger搬到blog.donews.com,这次又要再搬到my.donews.com。<br /><br />上次是因为blogspot在国内没法访问,这次搬是因为blog.donews.com总是出问题,而且可定制性很差。<br /><br />终于决定在自己的网站建起来之前,把家搬到my.donews.com上来。正好今天做完一项工作之后,有点心不在焉,就做做体力活。后面30多篇文章都是从blog.donews.com/idlecat511上生搬过来的。 <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-timestamp'> 时间: <a class='timestamp-link' href='http://idlecat.blogspot.com/2006/05/blog-post.html' rel='bookmark' title='permanent link'><abbr class='published' title='2006-05-22T18:22:00-07:00'>18:22</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/85135250382973506/6970844728790285738' onclick=''>0 评论</a> </span> <span class='post-labels'> 标签: <a href='http://idlecat.blogspot.com/search/label/%E6%9C%AA%E5%88%86%E7%B1%BB' rel='tag'>未分类</a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-1805373859'> <a href='https://www.blogger.com/post-edit.g?blogID=85135250382973506&postID=6970844728790285738&from=pencil' title='修改博文'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> </div> <div class='post-footer-line post-footer-line-2'></div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='http://idlecat.blogspot.com/search?updated-max=2006-07-16T17:38:00-07:00&max-results=7&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='较新的博文'>较新的博文</a> </span> <a class='home-link' href='http://idlecat.blogspot.com/'>主页</a> </div> <div class='clear'></div> <div class='blog-feeds'> <div class='feed-links'> 订阅: <a class='feed-link' href='http://idlecat.blogspot.com/feeds/posts/default' target='_blank' type='application/atom+xml'>博文 (Atom)</a> </div> </div> </div></div> </div> <div id='sidebar-wrapper'> <div class='sidebar section' id='sidebar'><div class='widget HTML' data-version='1' id='HTML2'> <div class='widget-content'> <div><script type="text/javascript">var addthis_pub="idlecat";</script> <a onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')" onmouseout="addthis_close()" href="http://www.addthis.com/bookmark.php?v=20" onclick="return addthis_sendto()"><img width="125" alt="Bookmark and Share" style="border:0" src="http://s7.addthis.com/static/btn/lg-share-en.gif" height="16"/></a><script src="http://s7.addthis.com/js/200/addthis_widget.js" type="text/javascript"></script></div> </div> <div class='clear'></div> </div><div class='widget Label' data-version='1' id='Label1'> <h2>标签</h2> <div class='widget-content list-label-widget-content'> <ul> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/%E7%BC%96%E7%A8%8B'>编程</a> <span dir='ltr'>(50)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/%E4%BA%92%E8%81%94%E7%BD%91'>互联网</a> <span dir='ltr'>(14)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/%E8%BD%AF%E4%BB%B6'>软件</a> <span dir='ltr'>(4)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/%E7%BD%91%E7%BB%9C%E6%8A%80%E6%9C%AF'>网络技术</a> <span dir='ltr'>(8)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/%E6%9C%AA%E5%88%86%E7%B1%BB'>未分类</a> <span dir='ltr'>(8)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/%E5%A8%B1%E4%B9%90'>娱乐</a> <span dir='ltr'>(5)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/IT'>IT</a> <span dir='ltr'>(7)</span> </li> <li> <a dir='ltr' href='http://idlecat.blogspot.com/search/label/Linux'>Linux</a> <span dir='ltr'>(26)</span> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>博客归档</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(6)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2009/07/'> 七月 </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2009/05/'> 五月 </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2009/02/'> 二月 </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2009/01/'> 一月 </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(14)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/08/'> 八月 </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/07/'> 七月 </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/06/'> 六月 </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/05/'> 五月 </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/04/'> 四月 </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2008/01/'> 一月 </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/'> 2007 </a> <span class='post-count' dir='ltr'>(25)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/12/'> 十二月 </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/11/'> 十一月 </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/08/'> 八月 </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/07/'> 七月 </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/04/'> 四月 </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/03/'> 三月 </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/02/'> 二月 </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2007/01/'> 一月 </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/'> 2006 </a> <span class='post-count' dir='ltr'>(75)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/12/'> 十二月 </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/11/'> 十一月 </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/10/'> 十月 </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/08/'> 八月 </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/07/'> 七月 </a> <span class='post-count' dir='ltr'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/06/'> 六月 </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://idlecat.blogspot.com/2006/05/'> 五月 </a> <span class='post-count' dir='ltr'>(41)</span> <ul class='posts'> <li><a href='http://idlecat.blogspot.com/2006/05/private-p2p.html'>Private: 开放而且资源共享的p2p平台</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/wiki.html'>架个wiki服务器,你用哪个软件?</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/wii.html'>热核聚变还遥遥无期呀,wii便宜卖了</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/elephants-dream.html'>一部动画片的诞生,Elephants Dream</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/linux_22.html'>Linux需要微内核吗?</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/linux.html'>Linux下清晰的中文字体</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/rss.html'>用手机看rss,免费的哦</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/blog-post_22.html'>大数运算,你用哪个库?</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/valgrind_22.html'>实战valgrind来优化程序</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/monokaffenovell.html'>mono,kaffe和Novell</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/udev.html'>让自己的驱动支持udev</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/pc.html'>pc上最快的发包工具?</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/ps3linux.html'>在ps3上跑linux…</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/gtkfaq.html'>GTK+编程FAQ之一</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/linuxio.html'>Linux下如何把IO空间映射到用户进程空间?</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/vanchannel.html'>继续讨论van的channel</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/valgrind.html'>valgrind,好东西,一般人我不告诉他~~</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/linuxwidget-superkaramba.html'>linux下的widget - Superkaramba</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/yahoowidget.html'>yahoo的widget</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/zim-wiki.html'>zim, 桌面wiki</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/van-jacobsonchannel.html'>Van Jacobson的Channel</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/tcp.html'>TCP协议各种变体的简介</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/lexyaccc.html'>用lex/yacc分析c语言代码遇到的难题</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/libsigc.html'>用libsigc++实现信号机制 (旧文转贴)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/automakeautoconf.html'>使用automake和autoconf管理项目的上手指南(旧文转贴)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/nstcp.html'>用ns模拟TCP,结果费解!</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/extensionfirefox.html'>用extension来武装你的firefox</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/linux-network-performance-monitor2005.html'>linux network performance monitor(发表时间:2005-12-30)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/lxr2005-12-29.html'>改进lxr的一些想法(发表时间:2005-12-29)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/tcp2005-12-10.html'>tcp测试程序的进展(发表时间:2005-12-10)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/blogspotmono2005-12-10.html'>很遗憾,blogspot又被政府封了,再谈mono(发表时间:2005-12-10)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/g2005-12-01.html'>预编译头文件大幅度提高g++的编译速度(发表时间:2005-12-01)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/net2005-11-30.html'>.net其实是个好技术(发表时间:2005-11-30)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/gtktips2005-11-25.html'>GTK编程的TIPS(发表时间:2005-11-25)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/private-python2005-11-24.html'>Private: python的多线程问题(发表时间:2005-11-24)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/tcp2005-11-24_22.html'>在应用层写了个tcp实现雏形(发表时间:2005-11-24)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/tcp2005-11-24.html'>tcp测试(发表时间:2005-11-24)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/windowsgtk2005-11-23.html'>在windows上安装GTK运行/开发环境(发表时间:2005-11-23)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/tcprevisit2005-11-19.html'>TCP协议revisit(发表时间:2005-11-19)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/kde35-2005-11-19.html'>正在安装kde3.5(原发表时间 :2005-11-19)</a></li> <li><a href='http://idlecat.blogspot.com/2006/05/blog-post.html'>再次搬家</a></li> </ul> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div><div class='widget Subscribe' data-version='1' id='Subscribe1'> <div style='white-space:nowrap'> <h2 class='title'>订阅</h2> <div class='widget-content'> <div class='subscribe-wrapper subscribe-type-POST'> <div class='subscribe expanded subscribe-type-POST' id='SW_READER_LIST_Subscribe1POST' style='display:none;'> <div class='top'> <span class='inner' onclick='return(_SW_toggleReaderList(event, "Subscribe1POST"));'> <img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/> <img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/> 博文 </span> <div class='feed-reader-links'> <a class='feed-reader-link' href='https://www.netvibes.com/subscribe.php?url=http%3A%2F%2Fidlecat.blogspot.com%2Ffeeds%2Fposts%2Fdefault' target='_blank'> <img src='https://resources.blogblog.com/img/widgets/subscribe-netvibes.png'/> </a> <a class='feed-reader-link' href='https://add.my.yahoo.com/content?url=http%3A%2F%2Fidlecat.blogspot.com%2Ffeeds%2Fposts%2Fdefault' target='_blank'> <img src='https://resources.blogblog.com/img/widgets/subscribe-yahoo.png'/> </a> <a class='feed-reader-link' href='http://idlecat.blogspot.com/feeds/posts/default' target='_blank'> <img align='absmiddle' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/> Atom </a> </div> </div> <div class='bottom'></div> </div> <div class='subscribe' id='SW_READER_LIST_CLOSED_Subscribe1POST' onclick='return(_SW_toggleReaderList(event, "Subscribe1POST"));'> <div class='top'> <span class='inner'> <img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/> <span onclick='return(_SW_toggleReaderList(event, "Subscribe1POST"));'> <img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/> 博文 </span> </span> </div> <div class='bottom'></div> </div> </div> <div class='subscribe-wrapper subscribe-type-COMMENT'> <div class='subscribe expanded subscribe-type-COMMENT' id='SW_READER_LIST_Subscribe1COMMENT' style='display:none;'> <div class='top'> <span class='inner' onclick='return(_SW_toggleReaderList(event, "Subscribe1COMMENT"));'> <img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/> <img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/> 所有评论 </span> <div class='feed-reader-links'> <a class='feed-reader-link' href='https://www.netvibes.com/subscribe.php?url=http%3A%2F%2Fidlecat.blogspot.com%2Ffeeds%2Fcomments%2Fdefault' target='_blank'> <img src='https://resources.blogblog.com/img/widgets/subscribe-netvibes.png'/> </a> <a class='feed-reader-link' href='https://add.my.yahoo.com/content?url=http%3A%2F%2Fidlecat.blogspot.com%2Ffeeds%2Fcomments%2Fdefault' target='_blank'> <img src='https://resources.blogblog.com/img/widgets/subscribe-yahoo.png'/> </a> <a class='feed-reader-link' href='http://idlecat.blogspot.com/feeds/comments/default' target='_blank'> <img align='absmiddle' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/> Atom </a> </div> </div> <div class='bottom'></div> </div> <div class='subscribe' id='SW_READER_LIST_CLOSED_Subscribe1COMMENT' onclick='return(_SW_toggleReaderList(event, "Subscribe1COMMENT"));'> <div class='top'> <span class='inner'> <img class='subscribe-dropdown-arrow' src='https://resources.blogblog.com/img/widgets/arrow_dropdown.gif'/> <span onclick='return(_SW_toggleReaderList(event, "Subscribe1COMMENT"));'> <img align='absmiddle' alt='' border='0' class='feed-icon' src='https://resources.blogblog.com/img/icon_feed12.png'/> 所有评论 </span> </span> </div> <div class='bottom'></div> </div> </div> <div style='clear:both'></div> </div> </div> <div class='clear'></div> </div><div class='widget AdSense' data-version='1' id='AdSense1'> <div class='widget-content'> <script type="text/javascript"><!-- google_ad_client="pub-1179705942788377"; google_ad_host="pub-1556223355139109"; google_ad_host_channel="00000"; google_ad_width=120; google_ad_height=240; google_ad_format="120x240_as"; google_ad_type="text_image"; google_color_border="FFFFFF"; google_color_bg="FFFFFF"; google_color_link="204063"; google_color_url="8FACC8"; google_color_text="477FBA"; //--></script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> <div class='clear'></div> </div> </div><div class='widget HTML' data-version='1' id='HTML1'> <div class='widget-content'> <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> try { var pageTracker = _gat._getTracker("UA-7640079-1"); pageTracker._trackPageview(); } catch(err) {}</script> </div> <div class='clear'></div> </div></div> </div> <!-- spacer for skins that want sidebar and main to be the same height--> <div class='clear'> </div> </div> <!-- end content-wrapper --> <div id='footer-wrapper'> <div class='footer no-items section' id='footer'></div> </div> </div></div> <!-- end outer-wrapper --> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/387437488-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AEUoTZoeWCj49Ape19hLl19m_IIR:1780979910813';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d85135250382973506','//idlecat.blogspot.com/2006/05/','85135250382973506'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '85135250382973506', 'title': 'Idlecat\uff1a\u522b\u8dd1\u504f', 'url': 'http://idlecat.blogspot.com/2006/05/', 'canonicalUrl': 'http://idlecat.blogspot.com/2006/05/', 'homepageUrl': 'http://idlecat.blogspot.com/', 'searchUrl': 'http://idlecat.blogspot.com/search', 'canonicalHomepageUrl': 'http://idlecat.blogspot.com/', 'blogspotFaviconUrl': 'http://idlecat.blogspot.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': false, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': '', 'encoding': 'UTF-8', 'locale': 'zh-CN', 'localeUnderscoreDelimited': 'zh_cn', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Idlecat\uff1a\u522b\u8dd1\u504f - Atom\x22 href\x3d\x22http://idlecat.blogspot.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Idlecat\uff1a\u522b\u8dd1\u504f - RSS\x22 href\x3d\x22http://idlecat.blogspot.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Idlecat\uff1a\u522b\u8dd1\u504f - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/85135250382973506/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseClientId': 'ca-pub-1179705942788377', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': true, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/ff2fc60a7f0d8424', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': '\u83b7\u53d6\u94fe\u63a5', 'key': 'link', 'shareMessage': '\u83b7\u53d6\u94fe\u63a5', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': '\u5206\u4eab\u5230 Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': '\u5206\u4eab\u5230 X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': '\u5206\u4eab\u5230 Pinterest', 'target': 'pinterest'}, {'name': '\u7535\u5b50\u90ae\u4ef6', 'key': 'email', 'shareMessage': '\u7535\u5b50\u90ae\u4ef6', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27zh_CN\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': '\u9605\u8bfb\u5168\u6587', 'pageType': 'archive', 'pageName': '\u4e94\u6708 2006', 'pageTitle': 'Idlecat\uff1a\u522b\u8dd1\u504f: \u4e94\u6708 2006'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': '\u4fee\u6539', 'linkCopiedToClipboard': '\u94fe\u63a5\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f\uff01', 'ok': '\u786e\u5b9a', 'postLink': '\u535a\u6587\u94fe\u63a5'}}, {'name': 'template', 'data': {'isResponsive': false, 'isAlternateRendering': false, 'isCustom': false}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Idlecat\uff1a\u522b\u8dd1\u504f', 'description': '\u4e00\u4e2a\u7a0b\u5e8f\u5458\uff0c\u4e3b\u653bLinux\uff0c\u7f51\u7edc\u534f\u8bae\uff0c\u4e92\u8054\u7f51\u7b49\u4e00\u767e\u591a\u4e2a\u65b9\u5411\uff0c\u65e0\u4e00\u7cbe\u901a...', 'url': 'http://idlecat.blogspot.com/2006/05/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2006, 'month': 5, 'rangeMessage': '\u76ee\u524d\u663e\u793a\u7684\u662f \u4e94\u6708, 2006\u7684\u535a\u6587'}}}]); _WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', document.getElementById('Navbar1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/3534753152-lbx__zh_cn.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/828616780-lightbox_bundle.css'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar', document.getElementById('HTML2'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_LabelView', new _WidgetInfo('Label1', 'sidebar', document.getElementById('Label1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': '\u6b63\u5728\u52a0\u8f7d\u2026'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_SubscribeView', new _WidgetInfo('Subscribe1', 'sidebar', document.getElementById('Subscribe1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AdSenseView', new _WidgetInfo('AdSense1', 'sidebar', document.getElementById('AdSense1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML1', 'sidebar', document.getElementById('HTML1'), {}, 'displayModeFull')); </script> </body> </html>