Fedora 9 升级达成!

虽然网上说可能会有风险,因为 F9 用 upstart 替换掉了 Sysinitv 启动,多年的启动习惯终于被改变了。不过看起来我的运气还成,直接 yum 成功了。

[root@comman ~]# uptime
01:05:37 up 9 min, 1 user, load average: 0.10, 0.15, 0.10
[root@comman ~]# cat /etc/redhat-release
Fedora release 9 (Sulphur)
[root@comman ~]# uname -a
Linux comman.org 2.6.25.3-18.fc9.i686 #1 SMP Tue May 13 05:38:53 EDT 2008 i686 i686 i386 GNU/Linux

明天有时间配一下期待已久的 ISATAP 接入,这样就有 IPV6 可用啦!

Admire 龙芯电脑

当机器是 512M 内存的时候,只能用 64bit kernel,否则只能用 256M 内存(这个还能理解)
当机器是 256M 内存的时候,只能用 32bit kernel,否则就会随机死机,是彻底死掉,不是 panic。

Reiserfs 看来真是要倒台了。

今天某站的 reiserfs 又不成了,列不出来目录,重启以后无法 mount。我在被窝里面被电话吵醒,然后起来 fsck.reiserfs。根据上次某人的经验,就用 fsck.reiserfs 做一次 –fix-fixable 就可以了。不过这个过程超过想象的漫长。

中间我准备上 reiserfs 的官方网站 www.namesys.com 上面看看,却发现域名已经无法解析,whois 结果如下

Registrant:
Namesys
Hans Reiser
6979 Exeter Dr
Oakland, CA 94611
US
Email: reiser@namesys.com

Registrar Name….: REGISTER.COM, INC.
Registrar Whois…: whois.register.com
Registrar Homepage: www.register.com

Domain Name: namesys.com

Created on…………..: Fri, Mar 24, 2000
Expires on…………..: Tue, Mar 24, 2009
Record last updated on..: Tue, Mar 06, 2007

看起来好像还没过期,不过也很有可能是注册商给多续了一年保护,以敲诈更多银两。 反正不管怎么说, reiserfs 从 Hans Reiser 进局子以后,怎么看怎么都像不太成了的样子,现在连主页都能倒掉。可怜我们这些套牢在 reiserfs 上面的用户了。

无责任闲谈 – LD_PRELOAD 和模块内调用

无责任闲谈 – LD_PRELOAD 和模块内调用

这个问题的提出是因为某天伟大的布总问了我一个问题。

如果某个 .so 里面有两个函数, 一个 foo ,一个 bar, bar 调用了 foo ,那么 bar 调用 foo 的地方应该是直接生成对 foo 的调用呢?还是通过跳转表来实现呢?

我们讨论了一下,都觉得如果没有加 -fPIC 的话,这个怎么也不应该通过跳转表来实现。但是布总却发现,如果之前弄一个 inject.so 里面包含一个叫做 foo 的函数,然后通过 LD_PRELOAD 来预先加载,不管编译时候有没有加 -fPIC,调用 bar 的时候,调用的都是 inject.so 里面的 foo 函数。这就有点奇怪了,ld-linux.so 怎么会去修改原来 .so 中 foo 对 bar 的调用呢?

还是反汇编一下看看吧:

不带 -fPIC

00000498 :
498: 55 push %ebp
499: 89 e5 mov %esp,%ebp
49b: 5d pop %ebp
49c: c3 ret

0000049d :
49d: 55 push %ebp
49e: 89 e5 mov %esp,%ebp
4a0: e8 fc ff ff ff call 4a1
4a5: 5d pop %ebp

带 -fPIC
000004a8 :
4a8: 55 push %ebp
4a9: 89 e5 mov %esp,%ebp
4ab: 5d pop %ebp
4ac: c3 ret

000004ad :
4ad: 55 push %ebp
4ae: 89 e5 mov %esp,%ebp
4b0: 53 push %ebx
4b1: 83 ec 04 sub $0x4,%esp
4b4: e8 eb ff ff ff call 4a4 <__i686.get_pc_thunk.bx>
4b9: 81 c3 4b 11 00 00 add $0x114b,%ebx
4bf: e8 fc fe ff ff call 3c0 // PLT thunk
4c4: 83 c4 04 add $0x4,%esp
4c7: 5b pop %ebx
4c8: 5d pop %ebp

其中相关的 PLT 内容如下:

000003c0 :
3c0: ff a3 10 00 00 00 jmp *0x10(%ebx) // 指向跳转表项的指针
3c6: 68 08 00 00 00 push $0x8
3cb: e9 d0 ff ff ff jmp 3a0 <_init+0x18>

-fPIC 的情况很好理解,跳转都是通过 PLT 进行的,直接去修改跳转表中的数据即可。那么没有 -fPIC 的情况,loader 是怎么能够修改调用让他指向另外 .so 里面的函数呢?

从汇编里面可以看出来,没有 -fPIC 的情况下面,对 foo 的调用指向的也不是 foo ,而是一个没有意义的地址,观察 .so 的 reloc 信息可知,有一条 reloc 指向 bar 对 foo 调用的地方,内容是 “foo”

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
000015fc R_386_RELATIVE *ABS*
00001600 R_386_RELATIVE *ABS*
000004a1 R_386_PC32 foo

因此在 LD_PRELOAD 的情况下面, loader 会查找 foo 的地址并填入 bar 对 foo 调用的地方。

这种按照名字 reloc 的方式在 Win32 下面似乎没有见到过。Win32 下面 reloc 只是用于修正 DLL 加载以后导致数据指针位置不对的问题,操作方法是简单的把位置上面的值减掉原基址加上新基址,相当于 R_386_RELATIVE 这种类型的 reloc。但是仔细想想,这种 reloc 其实并没有任何必要,RELATIVE 方式已经足够解决问题了,怀疑这个 PC32 的方式,就是单独为了支持 LD_PRELOAD 这一历史遗留产物而设计的。(我比较懒得查阅资料,谁查到了麻烦讲一下)

在 64 位下面,这个把戏不能用了,因为 64bit 下面函数调用一般还只是通过 E8 指令来调用 32 位范围内的地址,而 foo 函数的位置可能离 bar 调用它的地方超过了 2G,因此 ld 遇到这样的 reloc 会报告失败,要求你必须用 -fPIC 来编译。

有人可能会问, -fPIC 了不是会影响性能?这个确实没办法了,在很久以前大家没有意识到需要 module local symbol ,觉得除了 static 的所有函数都全局可见就好了,结果这个习惯就一直继承下来了,虽然现在 ELF 格式中确实支持 module local 的 symbol。但是因为历史上就是这么下来的,为了维持兼容性,只好继续保持这一行为。很多函数并没有跨模块调用的需要,只是因为有跨文件调用就不得不变成非 static 的,在上面说的这种情况下就会受到影响。

一个很土鳖的解决方法就是把所有函数都堆进一个 .c ,然后除了真正需要导出的函数,都改成 static 的。也许 gcc 现在支持什么扩展,可以将符号声明成 module local 的,不过我也是懒得查资料了,有人知道的话,请不吝赐教。 //bow

RPM vs DEB的争论

RPM vs DEB的争论

这个论题也算是一个老坑了,我总是看到很多人说 debian 系统如何如何好使,apt 多么多么强。而 RPM 系统里面包依赖关系多么乱啥的。因此得出 DEB 这个包管理系统要比 RPM 这个包管理系统要强的结论。不过在我看来,这些问题要么不是问题,要么跟包管理系统一点关系都没有。

先说 DEB 派的几个论据

1: apt 系统用起来很方便
对, apt 系统用起来确实很方便,但这是在 rh9 时代的事情。现代基于 RPM 的系统,基本都有相对还不错的管理器,比如 fc 用的 yum, suse 用的 yast 等,虽然这些玩意可能也有点小毛病,比如 yum 相对 apt 来说要慢一些,但是总体来说,并不是致命的缺陷。只要有容量比较大的源,一样可以很爽的用。目前看来, FC 正在往 deb 的大源方向发展,FC 的官方源里面东西也相当的多了。
2: debian 系统比 redhat 系列的好使
这个说老实话,没有特别觉出来,当然这个跟使用习惯有关。倒是我觉得 debian 太过顽固,居然能跟 mozilla 打起来,搞的 firefox 都得改名成 iceweasel,导致一些网页上面的认 UA 的 javascript 不好使。相比之下,ubuntu 比起来 debian 这样的革命者就好不少,至少不会因为意识形态的问题跟人打架。
3: RPM 包的依赖关系比较混乱
这个我其实觉得跟 RPM 本身没有什么关系,倒是跟做 RPM 的人的习惯有关系。不知道是什么历史原因导致的,RPM 发行版的打包者通常很喜欢把一个包拆得很碎,连一个 snmp 都要拆成三个包,而 deb 系统在这方面就没有这么激进,通常就是一个软件拆成 base 和 dev ,只有比较大的包才会考虑分一下。这样就造成 RPM 发行版的依赖关系要更加复杂,这些依赖关系都是人手写的,维护代价上升很可能就造成一些混乱。这个确实是 RPM 发行版存在的问题,不过只要你自己会 build rpm, 那么基本依赖关系还是可以解决的。

下面说我自己感觉 RPM 系统优于 DEB 系统的地方

1: 打包容易。RPM 系统只需要写一个 .spec 文件就可以打包了,而 DEB 的我看了半天说明也还是没有找到门道。还要建一堆目录啥的,这对专门的打包者可能不是个问题,对我就是想临时 build 一下的人来说,就有点浪费了。
2: 有 rpmfind.net 这个好网站。deb 给我的感觉似乎是想把世上所有的软件都给吸纳进源,确实 debian 的源容量相当之大,很多奇怪的软件也都在 deb 源里面,但是经常还是有些东西找不到的,这时候 rpmfind 网站就很好用,我经常的用法是在上面找到 SRPM 然后下来自己改改 .spec build 一个适合自己系统的出来。 而 deb 似乎如果源里面没有而你不掌握打包技能,那么基本你就只能当 ./configure 一族了。
3: 配置文件拆分不那么激进。跟拆软件包的策略正好相反,保守的 deb 在拆配置文件上面下的力气,要比 rpm 系列大很多,拿 httpd 来说, Redhat 系列直接就拆成一个主的和一堆散的放在 conf.d 下面的就好了。而 debian 则是拆成了很多小的放在 mods-available 目录里面,需要什么,就 ln-s 到 mods-enabled 里面。这样看起来挺好,但是配置文件这东西哪里是那么好拆的,有些逻辑不好处理,于是他又搞出来一个 xxx.load 和 xxx.conf 的东西。最后搞到我都不知道他这个配置文件到底包含了什么。配置一个我本来会配置的东西,还要研究半天他怎么拆的这个配置,搞的很麻烦。当然这个我承认是个人喜好问题。但是我认为作网站运维的时候,应该使配置文件简单化,只完成够用的功能,而不应该为了扩展方便弄成这么一堆花儿,回头出问题了排查都麻烦。
4: 商业软件对 RPM 系统的支持更好一些
很多商业软件只有 rpm 版本的,或者安装脚本就是按照 RPM 风格的系统配置文件做的。deb 系统下面虽然有 alien 这个工具可以转 rpm ,但是并不能转里面软件对系统路径的依赖,很多软件都是到固定的地方去读取系统配置或者调用系统程序的。

基于以上原因,我在我维护的所有 Linux 系统上面都是采用基于 RPM 的系统。而且我见到的所有用 Linux 的大型网络公司,基本都是在用基于 RPM 的发行版跑服务。我想很多情况下原因也就是在于,在运维人员看来,rpm 和 deb 都差不多,都可以用得很爽,而 RPM 发行版在商业软件支持上有小小优势,就用 RPM 发行版了。

最近评论

时光机

其他