Archives

不会说话的爱情

[audio:http://rm.sina.com.cn/wm/VZ200810142246175248VK/music/MUSIC0810151400008267.mp3]

更喜欢小河的这个现场版~


绣花绣的累了吧 牛羊也下山喽
我们烧自己的房子和身体 生起火来
解开你的红肚带 洒一床雪花白
普天下所有的水 都在你眼里荡开
没有窗亮着灯 没有人在途中
只有我们的木床它唱起歌儿 说幸福它走了
我最亲爱的妹呀 我最亲爱的姐呀
我最可怜的皇后 我屋旁的小白菜

日子快到头了 果子也熟透了
我们最后一次收割对方 从此仇深似海
从此你去你的未来 我去我的未来
从此只能在彼此的梦境里 虚幻的徘徊
徘徊在你的未来 徘徊在我的未来
徘徊在火里水里汤里 冒着热气期待
期待更好的人到来 期待更美的人到来
期待我们的灵魂附体 重新再来
重新再来 重新再来

一切都会过去

最近这几天状态实在不好。吃饭吃不好,以前吃完还感觉饿现在都吃不完;睡觉睡不好,一下班回来就昏昏沉沉,躺在沙发上就能睡着,昨天晚上在沙发上睡了一晚。实在睡不着的时候就去看会儿书,看到困了然后继续去睡。说是在睡觉,其实很多时间都在醒着或者半醒,在想各种各样乱七八糟的事情。想出去走走散散心,结果动都懒得动,什么都不想干。我也恨不得马上就精神起来,像以前那样,可是真的不行,这需要时间,希望过一段时间就会好起来。一切都会过去,不是吗?

其实我属于那种经常独来独往的人,习惯一个人去做很多事情,一个人吃饭,一个人去书店看书,一个人看电影,一个人去唱KTV……有时候也想身边有个伴该多好啊,但仔细一想其实那是不可能的,为什么呢?有谁可以在你想约的时候就约出来,随叫随到?心情好的时候出来高兴一下,心情不好的时候出来陪你一下?半夜睡不着了也可以出来说说话?即使是最好的朋友也不会,他/她也会忙,总有出不来的时候,因为各种各样的无法拒绝的理由。就算有个女朋友也不会,她也会有她的事情,也不可能一天24小时都可以陪着你,而且她心情不好的时候你也要陪她,她不想见你的时候你还得躲着她,照顾她比照顾自己还要累。父母会吗?也不会!很多时候父母根本就不在身边,即使回家去看他们也可能会吵架,代沟太深,很多东西他们无法理解。比如我爸妈,他们似乎永远都理解不了周末为什么不去上班?在他们眼里周末上班那才是天经地义,就像在我眼里周末不上班才是!我们谁也说服不了谁。

可见,其实人不管什么时候都是孤单的,只是有时候我们体会不到而已。我们孤单地来到这个世界上,以后也会孤单地离开。即使以后结了婚,你也会发现自己在某些时候会感到孤单。因为人和人之间总有各种各样的隔膜,永远无法消除,哪怕你们再亲近。一个人就是一个世界,你永远无法走入另一个人的世界中去,即使你们天天生活在一起,你也无法知道此时此刻他/她到底在想些什么。人,生来就注定是孤单的。

人是一种很有意思的动物,如果你仔细观察的话。上面说人其实孤单的,但人又耐不住孤单,于是就有了婚姻,就有了朋友,就有被我们赋予各种意义的事情去做,这样一个人才不至于在漫长的人生中感到过于孤单,它在群体中找到归属感,在婚姻中找到幸福感,在工作中找到成就感,在攀比中找到荣誉感。因为这些东西,人类就逐渐形成了一套自己的价值观,就是他们对这些东西的理解和追求。这就是所谓的人生,一代又一代地传承下去,一直演变到今天。不同的人对此又有不同的认识,于是就有了丰富的人类社会。看透了,你会发现,这一切的一切其实都是非常虚无的,只是人自己创造出来的各种不让自己感到孤单的借口罢了。

说到社会,马上就变得精彩起来了,尤其是当引入了钱的概念。钱是一个好东西,是人类的伟大发明。钱其实就是利,它只不过是把“利”这个抽象的东西实在化了。人从原始的幼稚的人进化到成熟的人,就是因为对“私有”,对“利”有了认识,意识到了自己利害关系,又加上有了社会的概念,于是就产生了阶级,一直延续到了今天。人类历史的演变其实就是阶级的演变。今天你再看人类各种各样的斗争,说到底无非就是一个“利”字,因为每个人、每群人,都想让自己有利可图。可人人都这样社会没法存在,于是就有了法律和道德,去约束人们,规定他们在某些不合理的情况下不能去谋取某些利益。

所以,人类社会其实是很荒谬的。人这一生就是很短暂很孤单,人生观、价值观等等一切的一切其实就是为了让人活得,或者让你自己觉得你活得,更有意义一些,让你有活下去的动力,让你不感到孤单。如果哪一天所有人都不再认同这些观念,那么它们就不会有任何意义了!

绝大多数人意识不到这一点,他们赖以生存的就是这些人生观和价值观,因为他们被教育如此。他们之中存在各种各样的偏见,这些偏见形成一种力量,这就是下面要谈的世俗。世俗的力量是很强大的,没有哪一个人能够左右得了,哪怕是古代的皇帝,现在的总统,因为即使他也天天被各种世俗所左右,被各种流言所困扰,不可能为所欲为。一代人只能做一代人的事儿,其实就是由世俗决定的,世俗决定了当前的社会是什么样子。

世俗是由多数人决定的,而多数人往往是愚蠢的,相比较那些少数的天才来说,所以天才往往被世俗所伤害,他们才想到去改变一些世俗。有些人成功了,我们称之为伟人,因为他们改变了我们世俗的一部分内容。可是改变世俗是需要很大勇气和力量的,这使得一个人成为伟人变得困难重重,而顺应世俗又是那么的容易,通常你什么都不需要做,世俗的潮流会像波浪一样推着你去顺应它。这很公平,你想成为伟人就得花很大的力气去改变世俗,而成为俗人什么都不需要做。没有人能够改变整个社会,因为没有人能改变整个世俗,世俗是靠时间和一些人一点一点去改变的。

人迟早都会死亡,人类这种贪婪的动物迟早都会灭亡,和宇宙相比较,人类又是那么渺小,所以人生其实是毫无意义的,因为任何意义都是人类自身捏造出来骗自己的。人为什么要活着?没有什么理由。或许我们应该去问问狗,它们似乎比我们知道得更多……

“我认识的人越多,我越喜欢狗。”

迁移 home 分区

之前装系统时用的是默认安装,结果/home没有单独分出。现在想装新的系统,所以备份/home里面的东西就成为一个问题了。后悔啊!还好,幸亏当时我用的是LVM,所以我可以动态调整分区。

我天真地以为直接用lvm调整即可,事实不是这样的,直接操作你会发现没有足够的PE,换句话说,我的lvm已经被占满了,需要先腾出一些空间来。

因为根分区是一个整体,所以必须得从别的系统进来然后进行操作。于是,我找了一个Fedora的LiveCD。首先检查已有的根分区:

e2fsck -f /dev/VolGroup00/LogVol00

然后缩小根分区的大小到120G:

resize2fs -f /dev/VolGroup00/LogVol00 120G

用LVM缩小根分区的逻辑卷大小到120G,这样就剩下100G给后面的/home:

lvm lvreduce -L120G /dev/VolGroup00/LogVol00

添加新的卷:

lvm lvcreate -L100G -nLogVol01 VolGroup00

好了,任务完成了一半,继续备份:

mount /dev/VolGroup00/LogVol00 /mnt/root

mount /dev/VolGroup00/LogVol01 /mnt/home

cp -R /mnt/root/home/wangcong /mnt/home

经过了漫长的等待之后终于完成,然后就可以安装新的系统了,要把新的LogVol01选为/home,而且不格式化。安装完毕后:

chown wangcong -R /home/wangcong

结束。

几个有用的 malloc 环境变量

或许除了LDDEBUG等少数几个环境变量,你对glibc的其它环境变量并不熟悉,比如 MALLOC_PERTURB

MALLOCPERTURB 很有用,它的作用是指定用来填充 malloc(3) 所分配的内存的内容,单位是字节。我们知道,malloc(3) 并不会对其所分配的内容进行初始化,所以如果直接使用这部分内存会出错。而 MALLOCPERTURB 就是用来解决这个问题的,你可以用它来填充这些内存,然后一旦使用了未初始化的内存,这部分内存就很容易被识别出来。所以它在某种程度上可以帮助我们检测未初始化的 malloc(3) 内存。

需要注意的是,用来初始化 malloc(3) 内存的值是 MALLOCPERTURB 的二进制取反(也就是~MALLOCPERTURB),但是 0 会取消掉这个功能。通常我们可以这样来设置:

export MALLOCPERTURB=$(($RANDOM % 255 + 1))

另一个是MALLOCCHECK,当设置了它时 glibc 就会使用另外一个 malloc(3) 的实现来检查一些简单的内存错误,比如多次 free(3) 同一个地址,off-by-one 错误等。它有三个值:0表示忽视检测到的错误,1表示打印错误到标准错误输出,2表示检测到错误就马上中止程序。更详细的描述可以参考手册

还有几个和 malloc 内存分配策略相关的环境变量是:

MALLOCMMAP_MAX
MALLOCMMAP_THRESHOLD
MALLOCTOP_PAD
MALLOCTRIM_THRESHOLD

它们分别等价于 mallopt() 的对应参数,可以参考 mallopt() 的手册。更详细的介绍见这里

母亲给我的最重要的东西

今天是母亲节,我不想仅仅表达我对母亲的感谢,因为母亲给我的东西是我这辈子都报答不完的,更别说只有每年的这一天了。

母亲究竟给了我什么?显而易见的是,她给了我生命,给了我一个完整的家,把我抚养长大。除了这些,她还给过我什么?哪些才是最重要的?我常常在想这些问题。

我的母亲是一个很普通的妇女,只上过小学和初中,当了一辈子的工人,她给不了我太多的财富,也给不了我太多的知识。她给我的全部东西中,我认为最重要的有两个:一个是从小就教育我的多读书,另一个是要有爱心。

小时候家里穷,搬过好多次家,但家里像样的家具就一直是那么陈旧的几件,一直舍不得扔。更别提衣服了,印象中她买新衣服的次数屈指可数。可就是这样,她还是鼓励我读书,小时候给我买各种童话书,每次进城都要带我逛新华书店。长大了,每次我想买参考书时她也都毫不犹豫,哪怕是我看了十几页就不再看了。她口口声声说家里没钱,不要浪费,可是在买书这件事上她从来没抱怨过。就是她,才让我养成了一辈子都受用的爱读书的好习惯。

上学时学校没少组织学生捐款,不管在几年级,我所在的班都算是比较好的那种,所以班里不乏一些家境很好的同学。每次捐款都是回去找她要钱,只要一说哪里出事儿了,捐什么款,她从来都不含糊的。记得有一次我竟然还捐得最多,和另外一个有钱同学一样。正是因为她我才懂得了为什么要去帮助别人。

现在她老了,更爱唠叨了,每次打电话都唠叨个没完,有时候我也觉得烦,可是一挂电话我就后悔不该嫌她唠叨,冲她生气。她也真是的,老是说养儿子不好,以后不孝顺、不会养她。其实她完全可以放心,只要是想起我小时候她为我做的那一点一滴,我觉得这一辈子都报答不完!

glibc定义的系统调用

最近有人问道,glibc 中对我们常见的那些系统调用的定义在哪里?比如write(2)recv(2)

这个问题我以前在看glibc的代码时注意到了。我们通常可以直接找到的所谓定义,比如下面这个:

[c]
ssize_t
libc_write (int fd, const void *buf, size_t nbytes)
{
if (nbytes == 0)
return 0;
if (fd < 0)
{
set_errno (EBADF);
return -1;
}
if (buf == NULL)
{
__set_errno (EINVAL);
return -1;
}

set_errno (ENOSYS);
return -1;
}
libc_hidden_def (
libc_write)
stub_warning (write)

weak_alias (libc_write, write)
libc_hidden_weak (write)
weak_alias (
libc_write, write)
[/c]

其实很明显,这并不是真正的定义,至少并不是你想找的那个。这个是什么呢?这个其实是write(2)的一个alias,而且还是weak alias,换句话说也就是,如果一个平台上没有定义自己的write(2),那么就用一个。而且从上面的代码也可以看得出来,这个函数仅仅是处理了一下errno,别的什么都不做。

那真正的定义究竟在哪里?说实话,我当初找到费了一番周折,找到它们并不容易,因为它们是编译时生成的!!可以从下面三个文件中看出来:

sysdeps/unix/make-syscalls.sh
sysdeps/unix/syscalls.list(sysdeps/unix/inet/syscalls.list)
sysdeps/unix/syscall-template.S

syscall-template.S顾名思义是个定义的模板,每个生成的系统调用都要参考这个模板,但是怎么用模板来“刻画”每一个系统调用呢?于是就有了syscalls.list,而make-syscalls.sh就是用模板和那个列表来构建生成系统调用定义的makefile,该makefile最终生成最后的定义。有兴趣的朋友应该仔细看看这几个文件。

现在再想想,这么做其实是有道理的,在Linux下,系统调用的真正定义有很多相似的地方,确实可以通过“模板”来生成对应的汇编,但是否真值得花时间去构建那么抽象的一个模板和框架?我说不清楚,本着“懒惰”的原则确实应该如此,不过看看模板本身似乎原因不仅仅是“懒惰”。

从这里我们也可以看出glibc的代码难读啊,比起Linux内核来,不仅仅是风格的问题,还有就是使用了太多的tricks,导致的结果也很显而易见,参与glibc开发的和参与linux内核开发的人明显不是一个数量级的。

Kimian Self Reproduction

看《GEB》时看到了这个东西,感觉很有意思。《GEB》在第 16 章中提到了这个东西,中文版的把它翻译成了“凯姆式自复制”。其实它类似于Quine)(如果你还不了解这个东西,可以在我的主页上找到我写的Quine),也是打印其本身,不过它是无意义的,也就是说编译器/解释器会报错,而错误信息本身就是它的内容!

在网上搜了搜,发现就这么一个页面介绍Kimian,里面给出的例子除了Perl的那个别的在Linux上都不行。所以我又自己特意写了几个:

zsh版的Kimian:

% zsh: command not found: zsh:
zsh: command not found: zsh:

Python版的Kimian:

% cat kimian.py
File “kimian.py”, line 1
File “kimian.py”, line 1
^
IndentationError: unexpected indent
% python kimian.py
File “kimian.py”, line 1
File “kimian.py”, line 1
^
IndentationError: unexpected indent

另一个Perl版的:

% cat kimian.pl
kimian.pl syntax OK
% perl -X -c kimian.pl
kimian.pl syntax OK

C版的Kimian:

% cat kimian.c
kimian.c:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute‘ before ‘.’ token
% gcc -w -c kimian.c
kimian.c:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘.’ token

有兴趣的朋友可以自己尝试去写写。;)