分类: 2010 June

新域名,好心情

测试feedburner是否已更新….

终于搬家了.

首先需要说明,我对政治没有丝毫的兴趣,GFW肆虐,我没有什么好说的,技不如人,努力学习就是了.只怪自己年 少无知啊,注册了godorz.cn,幸运的是,域名8月中就到期了,因此今天把博客比较完美的搬到了godorz.info,用的仍旧是以前的虚拟主 机.Btw,之前本来打算使用@zzzcn友 情提供的快速主机,但是没有Cpanel控制面板我真的不习 惯,导入和修改数据库都要用php代码来写是一件很悲剧的事,我不愿在自己不喜欢的事上多动脑筋.不管怎么样,还是得感谢@zzzcn.

Cpanel上有phpMyAdmin这种工 具,搬家就变成了很轻松地一件事,先把旧博客的文件打包到新博客,然后将旧博客的数据库导入到新博客,之后再用 UPDATE 表名 SET 字段 = REPLACE(字段, ‘旧域名’ , ‘新域名’); 语句修改一下文章,留言,图片(表 wp_options,wp_posts,wp_comments)等链接,然后搜索主题,将以前自己hack的统统更新,接下来要做的就是将在 feedburned托管的域名更新一下,最后在google网站管理员工具里验证新域名,之后提交xml,然后将以前的网址更新,google anlysist如法炮制,最后修改旧博客下的.htaccess文件,做个301转向,这样,域名就可以平稳的过渡了,一是不掉pr,二是不掉rss订 阅数,三是旧链接不死..

而这篇文章,就是提醒各位订阅http://godorz.cn/feed的童鞋,赶紧赶紧更新rss源吧..

垃圾收集

下面是看CSAPP时的读书笔记..Chapter10.10

垃圾回收

在C malloc这样的显式分配器中,我们可以使用malloc和free来分配,释放堆块.
在程序返回时,忘记释放已分配的块是一种很让人郁闷的事情.比如说,

void do()
{
	int *p = (int *) Malloc(10); // Malloc为malloc的包裹函数
	... // do something
	return;
}

函数do()分配了一块临时存储,当它不再需要p时,函数do()并未将其释放,这就导致了内存的泄露和浪费.按照UNPv2的说法,该临时存储是process-persistent的,它在程序的生命周期中都保持为已分配状态,毫无必要的占用着堆空间.

问题总是需要解决的.垃圾收集器(garbage-collector)就是其中的一个解决方案.它是一种动态存储分配器,功能是自动释放程序不再需要的已分配块(即内存垃圾),自动回收堆存储的这个过程就叫做垃圾收集(garbage collection).

垃圾收集的历史是相当久远的,它早于C的出现,目前仍是一个重要的研究领域.垃圾收集的算法很多,下面讨论的是Mark&Sweep算法,它比较简单,可以建立在已成熟的malloc包的基础之上,为C和C++提供垃圾收集.

基本原理

首先,不加解释的给出一张linux进程的存储器映像图,

GC(即垃圾收集器)将存储器看做是一张有向可达图(directed-reachability-graph).在该图中,节点可以分为两组,一组是根节点(root node),一组是堆节点(heap node).其中,每个根节点对应于一个不在堆中的位置,每个堆节点对应于堆中的一个已分配块,有向边 p->q 说明块p中的每个位置指向块q中的某个位置..注意,这里所说的位置,既可以是寄存器,又可以是栈里的变量,甚至是虚拟存储器中读写数据局域内的全局变量(见前图).当存在一条从任意根节点到达p的有向路径时,p称为可达的(reachable),否则,p称为不可达的(unreachable),不可达节点所对应的位置,即为内存垃圾.概括起来,GC的角色就是维护这张有向可达图,并通过释放不可达的节点来回收内存垃圾.

在具体的实现中,我们可以将GC作为一个和应用并行的独立线程,在后台进行垃圾的收集.下面是一个将GC加入malloc的例子,

当应用程序调用malloc时,如果malloc找不到一个合适的空闲块,那么它就调用GC,GC识别垃圾,调用free函数将垃圾回收.

Mark&Sweep

由名字就可以知道,Mark&Sweep收集器可以分为两个阶段,标记(mark)和清除(sweep),其中,标记阶段标记处根节点的所有可达的和已分配的后继,而清除阶段释放每个未被标记的已分配块(即垃圾).

小例子:

每个块对应着存储器中的几个字,其中,块头部包含一个字,要么是已标记的,要么是未标记的.

(1)标记前:

在标记前,堆由6个已分配但未标记的块组成,根节点指向第4块,第4块包含指向第3块和第6块的指针,第3块包含指向第1块的指针.

(2)标记后:

在标记后,第1,3,4,6块被标记(可达),第2,5块仍然是未标记(不可达).

(3)清除后

在清除后,第2,5块被回收.

算法

mark函数如下:

typedef char * ptr;

void mark(ptr p)
{
	if((b = isPtr(p)) == NULL) 
//如果p指向一个已分配块中的某个字,则返回指向这个块的起始位置的指针b,否则返回NULL.
		return;
	if(blockMarked(b)) //块b是否已标记
		return; 
	markBlock(b); //标记块b
	len = length(b); //块b的字长,包括头部
	for(i=0; i<len; i++)
		mark(b[i]);
	return;
}

标记阶段为每个根节点调用一次mark函数,如果p不指向一个已分配但未标记的堆块,mark函数就立即返回,否则,它标记这个块,并对块中的每个字递归的调用自己.每次对mark函数的调用都标记某个根节点的所有未标记且可达的后继节点.在标记阶段结束后,未标记但已分配的块就是不可达的,为内存垃圾.

sweep函数如下:

typedef char * ptr;

void sweep(ptr b, ptr end)
{
	while(b<end)
	{
		if(blockMarked(b)) //块b是否已标记
			unmarkBlock(b); //将块b由已标记改为未标记
		else if(blockAllocated(b)) //块b是否已分配
			free(b);
		b = nextBlock(b); //返回堆中块b的后继
	}
	return;
}

sweep函数在堆中的每个块上循环,释放它所遇到的所有未标记的已分配块.

C程序的保守的Mark&Sweep

对C语言来说,Mark&Sweep收集器一定是保守的,即每个可达块都被正确的标记为可达,而一些不可达节点可能会被错误的标记为可达的.导致这一问题的原因,是C语言不会用类型信息来标记存储器位置.因此,像int这样的标量可以伪装成指针.一个很典型的例子是,假如某个可达的已分配块在它的有效载域中包含一个int(注意,mark函数会对块中的每个字递归的调用自己),其值碰巧对应于某个其他已分配块t的有效载域的一个地址.对收集器而言,它是无法断定这个数值到底是int还是一个指针的.因此,它只能保守地将t标记为可达的,尽管事实上t可能是不可达的.

ps: 截图真是悲剧啊..
ps2: 博客域名随时可能改为godorz.info,感谢无敌的@zzzcn

无聊(4)

最近挺无聊的,一直在看电影,看书的劲始终提不起来.唯一能意识到自己存在的,是偶尔看看greader里攒了多天的star未读条目时,总会有的那么一丝震撼.我不明白的是,为什么世上会有那么多的牛人,以致于我总觉得自己这几年算是白活了.悲剧的是,震撼之余,我却没有丝毫的改变,依旧过着这么茫然的生活.

前段日子,csdn上出了个Obug老师的闹剧,我也只是傻子一般地看着双方的辩论罢了,不想读到陈硕同学对Obug的评论时,却彻底被大牛的光芒晒了个体无完肤.陈硕同学说,”连最基本的成员初始化列表和 const 修饰符都很少用到。这样的代码风格,在我们组肯定会被毙掉的。”. 我想,我该是被枪毙无数回的吧.再之后的讨论,看得我胆战心惊无地自容,大牛的见识,眼光,思想,纵是给我个三年,五年,十年,恐怕也不是那么容易就能赶上的.细节是重要的,可我明白,我欠缺的了解的,与其说是细节,不如说是底层.

凡事只要涉及到了底层,需要的知识储备瞬间就膨胀起来.操作系统,编译器,CPU,几乎都是应该了解的.比如说,struct { … } 占用的字节数,这是很常见也很简单的一道题,多数书本也给出了一个看似满意的答案,可事实上,字节对齐是不应被忽视的,甚至编译器的优化也是一个不该忽视的问题.又比如说,我不断学习,终于明白了线程安全是一个多么绝望的话题,即便层层锁,次次锁,可依旧有cache一致性和CPU乱序的问题,即便我解决这些问题,一度以为代码已经很完美的时候,突然看见一条评论说,HP-UX自身的线程本来就是有问题的…相比于未知的已知,已知的未知更让我不得不给自己竖起中指,我无法向自己解释清楚,为什么我会如此的弱小.操作系统自身的bug,这该是多么的黑暗.不了解底层,想解决这么隐蔽的问题,是不现实的.之前看unp,了解到mmap可以将普通文件映射到进程地址空间,甚至可以设置private或者share的模式,可我也只是感叹其强大罢了,这背后的映射,存储,寻址,装载,却是一头雾水的.

也许,我该多看看CSAPP,这是一本很浅显的书,用来深究是不够的,但拿来梳理思路,总结心得却绰绰有余了.

Btw,老丘,我高1同学,高2高3的同桌,大学三年住我楼下,嵌入式玩的相当不错的兄弟,下午要去移动最后一面了,真的希望他好好加油.

P.S: 不知道为什么,主机好慢,想换一个虚拟主机了,域名也一并换掉好了..