Hacking 《自己动手写操作系统》Chapter 1&2

——Writing x86 PC Bootloader With Free Software

本文内容已整理成一本电子书,请到这里下载

今天在看一本书,《自己动手写操作系统》(于渊,电子工业出版社),虽然很欢迎这样一本详尽介绍怎样写操作系统的书出现,但看完前两章后对作者的某些做法很不以为然。比如使用 Windows 作为开发平台,采用商业虚拟机作为测试平台,不是每个人都买得起这些软件的(我们要在心中牢固树立使用盗版软件就是犯罪的观念 X-D)。

我这篇文章的目的就是为了展示 Linux/Free Software 的强大,不使用任何商业软件,不用自己写的任何工具,使用免费的工具链,照样可以完成而且更高效地完成《自己动手写操作系统》前两章的 demo。

当然我也希望这篇文章为推动 Linux 和 Free Software 的发展出一点力,比如让部分读者(尤其是 EE 和 CS 学生)看完这篇文章后舍弃瘟都死,投身到 Linux 和 Free Software 阵营中来,或者《自己动手写操作系统》的作者在下一版(如果有的话)中完全使用 Free Software 来做 demo。

好了,下面开始,先介绍一下需要使用的工具。
操作系统:Ubuntu 7.04 Feisty,平台: i386 PC。
使用工具:gcc, binutils(as, ld, objcopy), dd, make, hexdump, vim, virtualbox。
上面所说的工具中,除了 virtualbox 虚拟机,剩下的工具在任何能用做开发环境的 Linux 版本上都是默认安装的。VirtualBox 也是遵从 GPL 协议的开源软件,可以从这里 [href: http://www.virtualbox.org ]下载。Ubuntu 只需要 sudo apt-get install virtualbox 安装即可。

首先,我们看第一个示例代码:
[wbyang@solrex-PC loader]$ more boot.asm
org 07c00h ; 告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
此段代码使用 Intel 格式的汇编语言写成,本也是用同样开源的 NASM 编译,但是鉴于很少有人在 Linux 下使用此汇编语法,它在 Linux 平台上的扩展性和可调试性都不好(GCC 不兼容),而且不是采用 Linux 平台上编译习惯,所以我把它改成了使用 GNU tool chain 去编译连接。这样的话,对以后使用 GNU Toolchain 编写其它体系结构的 bootloader 也有帮助,毕竟 NASM 没有 GAS 用户多。

上面的汇编文件可以用 AT&T 风格改写为:
[wbyang@solrex-PC loader]$ more boot.S
.code16 ;使用16位模式汇编(GAS 默认认为 .S 文件是 pure 32-bits i386 code)
.text ;代码段开始(为 link script 做定位)
mov %cs,%ax
mov %ax,%ds
mov %ax,%es
call DispStr ;调用显示字符串例程
INF: jmp INF ;无限循环(GAS 没有 $ 作为当前行标号的约定)
DispStr:
mov $BootMessage, %ax
mov %ax,%bp ; ES:BP = 串地址
mov $16,%cx ; CX = 串长度
mov $0x1301,%ax ; AH = 13, AL = 01h
mov $0x00c,%bx ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov $0,%dl
int $0x10 ; 10h 号中断
ret
BootMessage:.ascii "Hello, OS world!"
.org 510 ; 填充到 510 字节,使生成的二进制代码恰好为512字节
.word 0xaa55 ; 结束标志

但有一个问题, NASM 可以直接使用 nasm boot.asm -o boot.bin 将 boot.asm 编译成 bin 文件,GAS 不能。但是 GAS 的不能恰好给开发者一个机会去分步地实现这个过程,使编译更为灵活。下面请看 link script 和 Makefile:
[wbyang@solrex-PC loader]$ more solrex_x86.ld
SECTIONS
{
. = 0x7c00;
.text :
{
_ftext = .; //告诉链接器程序加载到内存的7c00处
} = 0
}

这个连接脚本的功能就是,在 link 的时候,将程序加载到内存 0x7c00 的位置(BOIS 将 PC 控制权转交给这个位置运行的程序),相当于 boot.asm 中的 org 07c00h 一句。有人可能觉得麻烦,还需要用一个脚本控制加载地址,但是 《自己动手写操作系统》就给了一个很好的反例:Chapter 1.5 代码 1-2,作者切换调试和运行模式时候需要对代码进行注释,而使用脚本控制,只需要编译时候调用不同脚本进行连接,就能解决这个问题。

这在嵌入式编程中是非常常见的处理方式,使用不同的连接脚本一次 make 生成某个程序分别运行在 board 上和 simulator 上的两个二进制文件 。

相信只要能耐心看到这里的人对下面 Makefile 中的内容都不会陌生。
[wbyang@solrex-PC loader]$ more Makefile
CC=gcc
LD=ld
LDFILE=solrex_x86.ld #使用上面提供的连接脚本 solrex_x86.ld
OBJCOPY=objcopy

all: boot.img

boot.img: boot.bin
@dd if=/dev/zero of=emptydisk.img bs=512 count=2880 #生成空白软盘镜像文件
@dd if=boot.bin of=boot.img bs=512 count=1 #用 bin file 生成对应的镜像文件
@dd if=emptydisk.img of=boot.img skip=1 seek=1 bs=512 count=2879 #在 bin 生成的镜像文件后补上空白,最后成为合适大小的软盘镜像

boot.bin: boot.elf
@$(OBJCOPY) -R .pdr -R .comment -R.note -S -O binary boot.elf boot.bin

boot.elf: boot.o
$(LD) boot.o -o boot.elf -e c -Tsolrex_x86.ld

boot.o: boot.S
$(CC) -c boot.S

clean:
@rm -rf boot.o boot.elf boot.bin boot.img

使用 Makefile,一个是方便,直接就可以生成可引导的软盘镜像文件,二是为了清楚,其间对源文件的任何处理都一清二楚。下面解释一下 Makefile 都做了什么:
第一步, gcc 调用 as 将 boot.S 编译成目标文件 boot.o;
第二步, ld 调用连接脚本 solrex_x86.ld 将 boot.o 连接成可执行文件 boot.elf。
第三步, objcopy 移除 boot.elf 中没有用的 section(.pdf,.comment,.note),strip 掉所有符号信息,输出为二进制文件 boot.bin。
第四步, dd 使用 boot.bin 生成可引导的软盘镜像 boot.img。

到此,我们使用开源工具链编译生成 bootloader 的过程已经结束,没有使用到任何商业软件,也没有自己写任何转换工具。《自己动手写操作系统》文中提到的 HD-COPY 和 Floopy Writer 都没有使用到。 为了验证也可以先用 hexdump -x -n 512 boot.img 将 boot.img 前 512 个字节打印出来,可以看到 boot.img dump 的内容和附送光盘中的 TINIX.IMG dump 的内容完全相同。这里我们也显然用不到 EditPlus 或者 UltraEdit,即使需要修改二进制码,也可以使用 vim 的 %!xxd 命令进行十六进制编辑。

写得真够累的,那个 virtualbox 就不说了,用法跟 virtualPC 没有什么大差别。安装上以后,新建一个虚拟机,加载 boot.img 光盘镜像到软驱,然后选择虚拟机重新启动,就可以看到红色的:
Hello, OS world!
当然,你如果喜欢的话,可以改成 "F-U_C-K Microsoft!" 不过要注意的一点是,做这件事是需要权限的,要把当前用户加到 vboxusers 组中,否则这个行为无法成功 :-)。

综上,很显然 VirtualPC 也不需要。《自己动手写操作系统》可怜的作者费了半天劲在瘟都死的 VirtualPC 里装 Redhat Linux,解决瘟都死和 Linux 的文件共享问题,解释了一番自己“工欲善其事,必先利其器”的动机,但我实在没看出有一点儿需要瘟都死的原因。瘟都死什么都不能给你,但 Linux 能给你整个世界!

Tor - Anonymity on Line

其实以前就见过 Baosheng 在博客里推荐 Tor 这个工具,据说可以访问 Wikipedia,只是当时潜意识里觉得太麻烦,就懒得搞。昨天晚上 Baosheng bg,请 ufx222, xum84, daoming, proline 我们一起吃饭,又提到了这个洋葱路由,今天就尝试了一下,果然好用。

简单来说,Tor 的功能就是,采用不同的“洋葱路由器(onion router 意思和代理服务器差不多)”来重定向网络请求,并且随时间更换路由,这样别人就无法监视你的网络访问情况,主要目的是为了保护隐私。而由此带来的副产品就是,onion routers 遍布全世界各地,所以就可以使用这个工具通过 onion routers 访问被“墙”封掉的站点(比如现在的 blogspot.com )。更多介绍请登录 Tor 官方网站 [href: http://tor.eff.org/ ] 。

从我的使用来看,刚开始使用访问网站速度可能慢点儿,用了一段时间之后速度就快很多了,大概是 Tor 自动在寻找洋葱路由服务器。而且最牛的是,我们公司的 DNS 坏了一小段时间,其间什么网站都没办法访问,而通过 Tor 居然访问正常,大概是 Tor 记录的是 IP 而不是 domain 吧。有意思的是访问 google.com 往往被重定向到某个欧洲的 Google 服务器,比如: google.de, google.es 之类的。

在 Linux 下 Tor 的配置很简单(我估计在 Windows 下会更简单,官方网站上有各种系统安装介绍):

首先,安装 Tor 软件,在 Ubuntu 下面就是:
sudo apt-get install tor
使用默认配置即可,即在 9050 端口打开一个 SOCKS 服务器。Tor 程序会以后台方式一直运行在系统里。

其次,为 Firefox 下载 torbutton 插件[href: https://addons.mozilla.org/en-US/firefox/addon/2275 ],安装。安装完成后,到"Tools->Add-ons->Extensions->Torbutton Preferences",在 "Proxy Settings" 中选择 "Use custom proxy settings",然后将前四个都留空,最后 "SOCKS Host:" 中填: localhost, Port: 9050,这样配置就完成了。

可以留意 Firefox 状态栏的最右端(窗口右下角),这时候会出来一个 "Tor Disabled",用鼠标点击该区域,就可以在 "Tor Disabled/Tor Enabled" 状态切换。这样在访问某些敏感站点时候就可以 Enable 它,在不需要时 Disable 它。也可以在 Torbutton Preferences中把这个文字格式的提醒改成一个洋葱头的图标提醒。

其实我想,不安装插件,只在网络设置中使用 SOCKS 代理也可以实现这种功能,如果这样的话,这里插件的作用只是启用和不启用代理的区别。那么,如果在校园网内,这个插件能否起到在 Firefox 的代理和插件这两个代理之间切换的目的呢?如果可以的话,就算不使用或者不能使用 Tor,这个插件也可以用作切换校园网代理使用了,倒也蛮方便的(只是我不需要用到了,所以就留给别人验证吧 X-D)。

PS: Yo2.cn 服务质量在下降,从 2007年7月19日8:25 到 9:00 之间都无法连接上,wget 可以下载但无法显示速度,更无法登录,最后出来一个错误:504 Gateway Time-out。唉,国产的 BSP 千万别学国产的足球队啊!烦死了,回去睡觉。

又回到北京了

好些天没有更新博客了(针对我的更新频率而言),原因很简单,有更重要的事情去做 :-)。

1 号到的北京,把寄放在同学那里的被子拖到租住的公寓,请邓飞、丽君吃了顿饭。2 号到公司报到,换了个办公桌,换了个电话。寄来的包裹和录取通知书同时到达,纳闷不已,为什么北京往南京挂号需要七天而南京挂号到北京只需要三天?害得我为了一张纸折腾(中科院的录取通知书着实简陋,信封是牛皮小信封,通知书就是一张请柬大小)。我原以为是通知书的那玩意儿是入学须知,但搞不明白的是,为什么入学须知要寄给我两次?

一毕业,这同学们好久不更新的博客都重新拾起来了,反而显得我有点儿懒。这下到公司工作,晚上的时间就多了些,可能又要恢复我正常的更新速度了。

这两天工作也没干什么事,FPGA 调试还不太熟练,模拟器又改了不少,而且更新中工作不太正常,所以就随便看看代码、看看邮件列表和一些 patch。GDB 的 mailing list 里这两天挺有意思的,有个人发了一个希望把 GDB 代码用 C++ 重写的邮件,然后一群大佬说这个问题别讨论了,各持己见讨论起来会没个头的。但是某个邮件里有巨牛的一句话:“The more C++ code I see, the more convinced I get that the language should die. ”让我叹服不已,哈哈。

重装了一个 Ubuntu,当然也装上了 beryl,比原来用着更方便了。Google desktop for linux 推出了,试用了一下,挺好的,特别喜欢它的两下 ctrl 就可以弹出搜索框,这样就免得我还得用鼠标把光标定位在 Google toolbar 里去。Google desktop 的 sidebar 没有在 Linux 版本上体现出来比较遗憾,那些小工具很有意思,但其实 Linux 本身就带有很多有一些的小玩意儿,喜欢玩的能把桌面配置得很 cool 或者 cute。为 Firefox 装了一个 IE7 的主题,看起来还是蛮好的,看来 Microsoft 的 UI 工程师也不是吃干饭的。但是 wine 现在还不支持 IE7,用 ies4linux 测试版装上之后,IE7 的 UI 效果一点儿也没有,真没劲。

毕业了,大家都在干不同的事,还有人(XHO)感叹没假期了,哈哈,准备成家立业的时候已经开始了,慢慢就该习惯了。

从中科大音乐站抓MP3的一个脚本

由于南京大学的 COS 音乐 FTP 被关闭了,原来很喜欢 COS 按歌手和专辑分门别类的风格,现在就不知道到哪里去下歌了。今天发现了一个好的音乐网站:中国科学技术大学音乐站,[href: http://music2.ustc.edu.cn ],按歌手和专辑分类,在教育网内速度算是相当快的,可以在线听。我就动了心思,想把专辑自动下下来。

中科大音乐站是这样的,你先选择歌手、专辑和歌曲,点击"播放"会下载下来一个 music@ustc.m3u 文件,使用播放软件打开就可以在线播放选中的歌曲。其 music@ustc.m3u 文件中每首歌的条目如下例:

#EXTM3U 双节棍
http://music2.ustc.edu.cn:8088/6e6bbc6495aec1f5fc719dcbc826ab4c%2F64%2Ff05523485d63a9c422393215c676f194.mp3

可以看出,中科大音乐站在存储 mp3 音乐文件的时候采取了某种文件名加密方法,很难直接猜出文件名,而且在提交 form 的时候采取 post 方式,不知道它的 action 文件接受什么样的参数,所以想在这一步上减少工作量是很难的。而且从网站上拿下来这个列表并不算很麻烦,因为每个人基本只会对某些专辑感兴趣嘛。那么下面要做的工作就是自动处理这个列表,将歌曲下载下来存在应该的位置和保存为正确的文件名。

Linux Bash Shell 脚本如下:

for album in $(ls *.m3u)
do
# Test the encoding of music list file.
  encode=$(file -i $album | awk ’{print $3}’ | sed -n ’s/charset=//p’)
if [ $encode != "utf-8" ]
then
  iconv -f gbk -t utf8 $album > ${album}.1
  mv ${album}.1 $album
fi
# Test if the album already exists.
if [ ! -d ${album%.*} ]
then
  mkdir -p ${album%.*}
fi
# Get the url list.
urls=(`grep -v "#" $album`)
# Download the song.
N=0
for song in $(grep "#" $album | sed -n ’s/#EXTM3U //p’ | sed ’s/ /_/g’)
do
  echo "Processing $song..."
  if [ ! -f ${album%.*}/${song}.mp3 ]
  then
    wget -O ${album%.*}/${song}.mp3 ${urls[$N]}
  fi
N=`expr $N + 1`
done
done

这个脚本所做的工作是:
1.找到当前目录下所有的以 m3u 为后缀名的专辑播放列表文件,循环处理它们。
2.检查专辑列表文件的编码方式,如果不是 utf-8 格式编码,将文件编码转换成 utf-8(为了处理歌曲文件名需要)。
3.去掉专辑列表文件后缀名 .m3u,以此为名字建立专辑目录。
4.得到专辑中歌曲的 url 列表。
5.下载歌曲到专辑目录中,并以对应的文件名命名,歌曲文件名中的空格被转化为下划线。

使用方法,先手动下载希望下载的每个专辑的播放列表(.m3u 文件),并将其文件名改为对应的专辑名,放到与脚本同一目录下,运行脚本,就会将每个专辑中的歌曲下载到以专辑名命名的目录下。

答辩通过

昨天下午论文答辩,纠缠那么久的论文,总算结束了。虽然自己仍然比较不满意,但是和某些同学比起来,我还是真真正正认认真真地写了一些东西,没有陷入欺诈之流。

说起欺诈,只能对很多人的做法无语。我不赞成这种做法,但是也能体会他们的难处。上次和 baosheng 聊天,他告诉我,他很想不通南京大学的学生为什么会在该做论文的时候天天玩游戏。在这一点上我有点儿无言以对,因为这就是我身边很多同学的生活状态。也许是大家觉得学士学位论文太不重要了,也许是他们对自己做的东西没有丝毫兴趣,也许就是从进大学后就培养出来的习惯,总之就是他们不在乎这个。我很能体谅吴朝阳老师不太愿意带本科生论文的原因,带本科生论文,只能是看着他们做的垃圾东西和垃圾效率生气又毫无办法。

不过有一点不得不值得我们思考,如果说一个两个学生这样,可能归结于个人的因素,但当这种心态成为一种群体意识的时候,就不能仅仅将责任推到学生身上了。说到底是教育制度的问题,但我觉得大学仍然可以做很多。如果老师们懂得如何激发学生学习的积极性,多几个对待学术方面严谨并且偏激的老师,造成正常的好的学术氛围,甚至多几个"愤青"同学,这个状况大概就会好很多。总之,一个好的大学,不应该现在这个样子。

=========={我是废话的分割线}==========

答辩完了,却还是有很多事情要做。大概是大家一直以来的惯性思维吧,虽然我不是毕业委员会里事务的负责人,但无论何事总会找到我,反而比自己负责更忙。不过也算是最后一次为大家服务了,也蛮愿意的。

前两天去南京的 Lonicom 做技术支持,只花了一个多小时就帮他们找到了 bug,PM 好好地表扬了我一番,这种感觉真不错。可能明天或者周末还要过去,我这个小实习生可给公司节省了不少银子啊。

今天晚上南大 Open 社团将在浦口举行本学期最后一场讲座,而且召集鼓楼 Linux User 商讨鼓楼 LUG 成立事宜。正好回去浦口怀念一下混在浦口的日子,希望能见到 baosheng, Lv, godtang, caibaiyin, dolphin9, abcx 这些朋友,可惜 snc 去不了。比较有意思的是,最近老认识 01 级的师兄,Linux 现版主 godtang 居然也是南大数学 01 级的,以前竟然没发现。

Blog Suggest

今天早上爬起来,看到一篇非常非常好的文章:你应当如何学习 C++(以及编程)(rev#1) [href: http://blog.csdn.net/pongba/archive/2007/05/16/1611593.aspx ]。

由于文章和评论都相当的长,而且作者加了 rev#1, 大概还是准备把这篇文章继续写和修改下去,我就不在博客里全文引用了。这篇文章和它的所有评论都值得仔细读一遍。

其实在一开始我学习的语言就是 C++,显然在一般情况下,教授 C++ 的书和教授都会每每提及 C 指出它的不足和 C++ 的优点。我在学校期间也丝毫不掩饰对 OO 的 C++ 的热爱和对简陋的 C 语言的鄙视,并因之也鄙视那些学 C 语言的人。当我听谁谁谁说正在学习 C 的时候我就会告诉他/她,C 语言已经过气了,功能太简陋而且要成为历史词汇了,还是学 C++ 吧!大概是因为 C++ 比 C 多了那么两个让人感觉骄傲的加号,当时愚蠢地以为学习 C++ 的人都能比学 C 的人更加地昂起头走路,想想真是太 rediculous 了。

我在大学期间也学了不少语言,虽然说没有太深入了解,但基本的使用还是没问题的。也曾经师从吴朝阳学习并分析过 STL 的代码,语言间的比较和对库深入的学习,也让我更加深信 C++ 的优越性。当时的我甚至非常愚蠢地认为,既然有 C++,C 语言早就应该淘汰了。

但是这些认识当我真正开始写工程应用的 C 语言代码时完全改变了,大学期间实验性的代码能说明的问题太少了。我仍然承认 C++ 很优秀,是很好的程序设计语言,但是并不是每个项目每个人都适合用 C++。在现在的我看来,C++ 太累赘了,除非是有非常好的可以使用 template 的环境,我不会选择 C++ 做为开发语言。很可能有 C++ 的狂热爱好者会鼓吹面向对象的设计,封装、派生、多态等等一些乱七八糟的理论(其实我以前也是其中的一个),但是,就像 云风 在博客里所说:"不过对这些(C++ 和 OO)了解的再多也不为多,每次面临新的设计时,就可以找到足够的理由不用 C++ 不用 OO 。对,就算是用 OO ,我也可以保证对象设计的整洁清晰;但我更清楚的知道,其实我可以不用它。"

我不像云风那样有着那么多年的游戏设计和开发经验,还没有过自己设计一个软件的机会。但是在我移植 GDB 的时候,我越来越体会到 C 语言的美好。我真的想劝说那些鼓吹 C++ 的人,请读读 Linux/Unix Kernel, GCC, GDB 的代码,就算你读过以后仍然坚信 C++ 是最好的,但我相信你不会再认为 C 语言是个垃圾语言并不再适用于当今时代。你会发现很多很多需要使用对象或者其它 C++ 特性的部分都可以通过精巧的设计来避免,而且虽然鼓吹 C++ 的人一直会宣扬 C++ 的代码重用可以精简代码等等,但在应用中你就会发现,C++ 代码的规模在正常情况下要远比同等功用的 C 语言的大(否则嵌入式领域就不是 C 语言的天下了)。

还有一点我很不满 C++ 的地方是在 GDB 的使用上,相信用 GDB 调试过 C++ 代码的人都深有体会。Readline library 并不支持双冒号"::"在命令中的自动补全,所以在成员函数上设断点是非常痛苦的事情。当程序中使用模板的时候,一个函数标识符的长度会很轻松的上几百,命令行补全一失效,不得不手工输入。所以当需要在类的成员函数上设置断点的时候,都要使用一些技巧。比如在类名上使用命令自动补全,在列表中寻找到自己需要的函数,拷贝保存下来它的名字,然后再通过粘贴设置断点。如果仔细点儿你就会发现,成员函数的第一个参数其实是 this 而不是在函数声明时候的第一个参数,这会在调试期产生误解。C++ 简化了程序员的思考,但是让底层的中间文件和目标文件变得更加混乱。

C++ 很优秀,但不是万能灵药。不是学了 C++ 就了不起,不是学了 C 就低人一等,就像 pongba 所说:"一般性的编码实践准则,以及基本的编程能力和基本功,乃至基本的程序设计理论以及算法设计。才是真正需要花时间掌握的东西。" "熟练运用一门语言绝不意味着要把它的边边角角全都记住。"

——但,C++ 的犄角旮旯实在太多了!

最后,特别推荐 pongba 的博客"C++的罗浮宫"[href: http://blog.csdn.net/pongba ]。pongba 者,刘未鹏也,南京大学数学系 2001 级,也算是我的直系师兄了(^_^)。翻译过:Working Effectively With Legacy Code, Exceptional C++ Style, Imperfect C++。

An Old Friend

半夜了,室友们仍然没有睡觉的意思。鼓楼比浦口管理松很多,温度高于 29℃ 宿舍楼就不熄灯了,直接导致的后果是某些人看电影到深夜,某些人打魔兽到深夜,某些人无聊到深夜。

因为 Linux 下的 Ctex 中文字体特别不好看,QQ 不能登录,不知道如何加载电影字幕等等诸多原因,用 Windows 的时间明显变长。在某部分无聊的时间内,浏览了一下 QQ 好友们的空间。

很久以来与老朋友们的联系仅限于短信和电子邮件,也是渐渐地趋于稀疏。不太多人写博客,就算有,恐怕也没几个人像我更新那么频繁。今天闯进好久好久没见到的一个初中同学的 QQ 空间,该生以安妮宝贝似的文字把我小小地震撼了一下,还是当年的赅子吗?唤起很多旧事的回忆:

赅子,初三时候坐我前排,颇有惊世骇俗之态,亦有不同常人之能。有若干历史事件加传奇让我记忆犹新:

历史事件:

赅子的母亲也是我们初中的老师,所以就被我们万恶的初三班主任马xx整得很惨(鉴于马xx的儿子也是我同班同学,此处略去真名并省略脏话两千字)。赅同学骨头极其之硬,可以说让我叹为观止,绝对是地下党加卧底的最佳人选!具体的事件就记不清了,但我脑子中能浮现出很多幅初三班主任马xx殴打他的画面,是真的殴打。如果事件不大,基本就是拿着书朝头上招呼,猛砸猛呼;有两三次比较严重的事件,马xx把他拉到教室外面用脚往身上踹。有的人可能不信,初中老师怎么可能体罚那么严重。但像我这么从小老实听话的孩子都被他皮鞋踹过疼了一个星期,原因仅仅是在上体育课前的课间和高中部的人踢了会儿球(他禁止我们踢球)。

我们班男同学基本都挨过打,赅同学也挨打,没什么不同。但赅同学与众不同就在于挨打之频繁以及挨打之功力。大概马xx打赅子的频繁程度和严重程度仅次于揍他儿子了,但赅子挨打的时候,从来都是一声不吭。无论问他什么事情,他绝对不会说半句,就算自己有理,他也从来不为自己辩解,你打他就像打一根木头。惭愧的说,其实这句话我也深有体会,因为我坐在他正后面,基本也是把他当作沙袋,什么时候郁闷了就朝他背上打两拳,绝对是一点儿反应都没有。哪儿找这么好的沙袋啊?

赅子很喜欢踢球,当时大概只有他不怕马xx的淫威敢在放学后到我们自己的操场上踢球,我们班的其他学生全是骑车到我们县的重点高中或者找个偏僻的小空地去踢球,这也是他挨打频繁的原因之一。很多人都踢球,踢球本不是什么惊世骇俗的事情,但是赅子就能做到惊世骇俗的就是,他能穿着三角内裤和拖鞋从家里出来,然后跑到学校操场去踢球,我想有这份经历的哥们大概不多。

传奇:

所谓传奇者,就是未经亲眼看到的事情。赅子有很多件,当时班里经常传说他的事情,记忆尤深者有两件。

一件发生在我们同班那年寒假。寒假开学后,某日,班主任马xx面带笑意地问赅子,你家的玻璃都安上了吧,你小子很厉害呀。当时就觉得纳闷,什么时候见过马xx笑那么阴险那么开心啊?一问才知道,这小子寒假把家里的玻璃全搞碎了!我们那有一种礼花,大概像饼干筒那么粗吧,直径大约十几厘米,点着以后会喷出来火花,一般是正月十五在家放。那小子不知道从哪儿搞过来一个那么粗的炮仗,在院子里点着了,可想而知有多大威力,"砰"的一声家里和邻居家的玻璃全都被震碎了,他在家也挨了一顿好打。

一件发生在小时候,我同桌给我讲的。我们县在盖建设银行家属院的时候,挖出来一个防空洞,当时很多人进去玩。因为没有照明,进去都是黑乎乎的,他们小孩子就乱摸。赅子比较背,摸着摸着就摸到了一坨屎,手上那个臭啊!本来是很倒霉的事情,谁知道这小子一转身就往别的人身上、脸上抹,抹完就跑。出来以后他们几个在一起玩的家伙都快给笑死了,然后一直就被传为笑谈。

就是这样的一个孩子,现在居然用那么忧郁那么脆弱的语言去抒发心中抑郁,去表达自己,我是无论如何也不会想到的。

孩子长大了...

孩子们长大了...

MSRA-UCLA

今天居然收到微软那个什么 MSRA-UCLA 计划的回信,申请都发给他们一个月啦这会儿才回信说收到了,我都快忘了这事儿了。

其实我也根本没抱什么希望,MSRA 啊,UCLA 啊,这计划国内才招十个人,能要我?所以那个申请表我也随便填填,连推荐老师都没有就给寄过去了。只是因为那次在北航听了一次 MSRA 什么图形计算组的头儿的讲座,看到 MSN 视频时候加面具挺有意思的,就申了一下那个方向。

唉,不是不想去啊,虽然平时都用 Linux 鄙视 Windows,使用 gcc 鄙视 VC,但我对微软还是有些敬意的,毕竟能做到如此地步也不易,当然很想能到微软实习了。川大那个牛人唐前两天也收到了 MSRA 的实习邀请,能见见也好啊。不过这事儿咱说了不算,况且我现在逐渐想往 Compiler 方向转,进去 MSRA 也学不到太多东西,还是留在现在公司实习比较好,有牛人提点啊。嘿嘿,咱自己几两水儿咱也知道,要是 MSRA 真给我发面试邀请了,那就得说我运气不是一般的好,如果我能通过面试,那就说明老天太青睐我了。不过真有机会去面试那就相当近啦,西格玛大厦就在我上班的路上,天天上下班我都要仰慕一番。BTW:有时候到沃尔玛吃饭还能碰到 MSRA 的员工呢,难道西格玛里面的食堂也很烂吗?

只当是一个梦想吧,让我清楚一下自己的定位。我还是得多考虑一下回学校的事儿,大概会是在 29,30 左右回家,然后 3,4 号回南京,该买票啦。唉,论文草稿完成了就一直懒得改,到现在才把其中一张 stack frame 图示重画了一下,改成了比较典型 MIPS O32 调用约定。剩下的还是回学校再改吧。

四年喽,要毕业喽,回去讨饭喽。

龙芯

这星期算是比较闲的一个星期,很多工作要等别人的进度,而且 ^_^,我自己也有想偷懒的因素。中间我居然花了一整天时间浏览了一下 《See Mips Run》,因为是 MIPS 的老员工出的书,写得还算不错,好像去年 10 月份还出了第二版:《See Mips Run Linux》,只是电子书现在还不太好找。

《See Mips Run》可以作为一本了解 MIPS 体系架构和编程的教材,甚至可以作为加深理解计算机体系架构的参考书。因为它几乎涵盖了体系结构设计和程序底层实现的所有方面,而且能将 RISC 结合某种特定的 CPU 进行探讨,又没有一般手册的枯燥,在这本书中可以了解到各种理论模型的实际实现方式。也有个缺陷就是它不够新,它所关注的是 R10000 以前的 MIPS,特别注重的是 R4xxx,但这些也是 MIPS 的经典之作。

在当前很多的嵌入式芯片中的设计中都可以看到 MIPS 的影子,包括计算所的龙芯(Loongson),更是受到 MIPS 的深刻影响。从一则新闻就可以看出来:2007年3月28日下午,中科院计算所与意法半导体在人民大会堂举行龙芯处理器技术合作签约仪式。龙芯通过该合作获得了 MIPS64 架构全部许可使用权,而意法半导体通过合作取得龙芯处理器芯片在全球制造和销售的授权。

随便扯点龙芯的话题,最近慢慢地了解了一些龙芯神话,也算揭开了一点龙芯的面纱。不是说龙芯不好,计算所的研究人员的确很优秀,龙芯做得也很好,很厉害。但是作为中国的科研机构,总会有一些很有意思的现象,就比如龙芯总是拿自己跟奔腾比。有这样的话:"最高主频达到1.0GHz,实测性能超过1.5GHz奔腾IV处理器的水平。"我以前看到这种说法总是觉得,哦,好厉害。只是现在慢慢懂了,龙芯和奔腾的 x86 根本不是同一个架构,这种比较可以说毫无意义。拿寄存器来说,龙芯 2E 总共有 64 个定点寄存器,64 个浮点寄存器,而奔腾 IV 是 16 个定点寄存器和 16 个浮点寄存器,可以想象四条腿的马和两条腿的人赛跑的景象。

当然,不是寄存器多就肯定快,也不是寄存器多就好,只是采用 MIPS 体系架构的 CPU, 使用了那么多快速存储设备,主频相同情况下某些方面性能高点当然是很正常的事情。作为 RISC 的龙芯和 CISC (相对) 的奔腾,它们两个的流水线技术、指令集、内存访问基本不同,可以说没有什么可比性。但是为什么连用户手册里龙芯都是拿自己和奔腾系列比较呢,而且只比主频?显然是看起来好看,就像很多公司发布 CPU 都会专门找测试集合一样,这样能忽悠人。

我不相信龙芯的开发人员会真拿与奔腾系列的参数比较当事儿。但很显然的是,中科院、科技部和国家领导们希望它与奔腾比,因为砸下了那么多钱却只看到和一个自己都没有听说过的芯片比性能,谁爽啊?也没办法跟上头交代啊!中国老百姓也希望它与奔腾比,因为是人都知道奔3奔4,你说别的咱老百姓也不懂啊。就拿算是精英阶层的大学生们来说,不知道 PSP,iPod 是什么东西的大概没几个,但知道 PSP 用的是两块 MIPS CPU, 知道 iPod 用的是 PortalPlayer(NVIDIA now),nano 用的是 ARM9, shuffle 用的是 SigmaTel STMP 的有几个,听说过这几个名词的又有几个?龙芯相关公司也希望它跟奔腾比,因为总是要糊弄老百姓的,让科研人员和媒体忽悠一下比自己忽悠效果好多了。

还有一句中国的科研机构经常挂在嘴边的话:"拥有全部自主知识产权。"这句话说起来很有气势,但做起来有那么容易吗?像龙芯,采用了多少 MIPS 架构的东西,连指令集都那么的相似,我不懂这些方面知识产权保护的方式和内容,但说龙芯拥有全部自主知识产权,我不信。就像中国的麒麟操作系统一样,你是改的别人的内核,在宣传中说"该系统已通过自由标准组织Linux标准基认证"的同时还说拥有自主知识产权,真当老百姓是傻子啊。

可以这样说,如果不使用 Linux,基本上没有亲切了解龙芯电脑的机会,因为龙芯上现在只能跑 Linux,而且我想,龙芯在可以预见的时间内,基本不可能赢得 Windows 的支持,就算是 Linux,它也只是支持一小部分。所以,龙芯的存在,和老百姓的 PC 没有太大关系,龙芯的市场也只能是在嵌入式和服务器领域,很难进入桌面市场。但是,龙芯的存在,给了中国一个机会,在处理器市场上竞争的机会,谁知道未来是什么样呢,别管手中的东西是好是坏,总比从敌人那里拿来的用着顺手。只是很难那,计算所的老师都说,想达到 Intel 的水平,那得至少 20 个计算所去做,还得国家鼎力支持。龙芯能做的现在的样子,很不容易了。只要别重蹈汉芯的覆辙,为了赢得国家和民众的支持,吹牛也吹点吧,只是别吹破了就行。我的同事有好多计算所出来的,有的还担过教职,他们对龙芯评价也很高,但都说,龙芯项目现在没多少真正厉害的人了,有能力的都跑国外了,看来龙芯的发展也并没有那么乐观。

呵呵,之所以聊龙芯的话题是因为好像公司下星期会来几个参与过龙芯项目组的计算所毕业生,忽然想起来了就扯点。毕竟算是中国芯片产业的希望啊,关注的人越多,才有可能变得越好。

Life Pieces

忍了几天,又想写点东西了。论文初稿已近完成,这些天倒也充实,白天工作,晚上写论文。只是因为公司在装修一个硬件实验室,好几天吵吵地不行,不然大概已经完成,也不必为食言而发愁了。

刚看了一个新闻,什么 Google 又出拼音输入法,还为词库和什么狗纠缠不清。只可惜常用 Linux 系统,那个 EXE 在我电脑上也没甚用处。其实我对输入法要求相当低,只要能支持智能 ABC 的双拼规则,我就愿意使用。以前发现过一个紫光可以自定义双拼规则的,我把回忆到的智能 ABC 的所有双拼对应的键填进去,费了老半天劲了,结果发现紫光会让我的系统崩溃着玩,立马放弃了。自从用过了 Scim,在 Linux 下我再也不会选择别的输入法了。为什么呢?就因为 Scim 可以选择很多种双拼方案,而且非常友好地支持了智能 ABC 的双拼。从实践上来说,我甚至认为 Scim 比智能 ABC 做的还要好,因为它的词频记忆绝对比智能 ABC 的更智能。当然了,和王三表同志所弘扬的黑马输入法没法比,但是黑马支持智能 ABC 的双拼吗?如果黑马支持,我立马就去买套用。其实对于习惯于词输入的人来说,整句的词库并没多大意义,不过,说不定我会改变一下这个习惯。我很期待 Windows 的 Scim,但如果 Google 的输入法能像 Scim 一样,我也会把自己在 Win 下的首选改为它。其实选择输入法可不像葛优选手机一样,哪家人多选哪家,而是哪家符合自己习惯和需要就用哪家。从 N 年前养成的输入习惯到了现在,改起来有那么容易吗?

还是一个软件的问题。偶然看到孙燕姿又出了新专辑,心中痒痒地慌,又偶然看到心仪很久的魅族 M6 降价,心中又痒了一下,几痒几不痒就让我到村里搞了一台 4G 的,看着爱不释手啊。咱的耳朵不是金耳朵,硬件好不好也听不出来,不过我算是充分地认识到了魅族软件的垃圾,那是相当的垃圾啊!!!不知道魅族软件工程师是怎么想的,一插到 USB 上就屏蔽掉所有的按键,也只能怪我一直无所谓于所谓的"安全删除硬件"。直接把线从电脑上拔下来,然后发现所有按键依然被屏蔽,屏幕上依然显示"USB 连接中",NND 直到电耗完。怎一个变态逻辑了得???要不是咱想支持国产,而 iPod 又不支持 FM,我真后悔没买个 Nano,水 2G 才 900 。

又是一个软件的问题,不过是和软件工程师有关的问题(咳咳,我的意思是程序员)。天宝兄弟两天前在博客上发泄了一通,http://www.liongg.net/?p=104 ,大肆宣扬对某个国内知名 GIS 公司对待实习生方式的不满,一肚子苦水啊。看过一本书,好像叫什么 Extreme Programming xxxx ,里面谈到了如何能让团队成员高效率地开发程序,如何让团队成员有满足感。想想我能进现在的公司很幸运啊,虽然公司不大,但做的事情很厉害,员工也全都是精英,而且工作的氛围相当的好。怎么说呢,能有一种被别人重视的和需要感觉真的能让工作起来开心许多。我也和很多在北京工作的程序员交流过,能够有我现在这样的工作环境的还没有遇见过,尤其是在上地中关村产业园的那些小公司,我基本没留下什么好印象。所有的都是 N 多人坐一排,不准上网,不准做和程序无关的事,电脑没有光驱,USB 口被封掉,N 多人一个电话,天天加班没有加班费,工资很低,总之就是把员工当贼看待,当民工使唤。不知道像 Google 这样的公司是不是真如宣传中那样,反正微软和 IBM 除了有钱也不是什么太好的地方。唉,找到一个适合自己的公司也不易。反正啊,我在这也干的不错,也打算毕业以后马上来公司继续做事。经理昨天还问我,毕业以后什么打算啊?我说,毕业以后还想过来干,反正在家也没什么事做。经理说,好,等你毕业过来我们就不把你当 intern 了,当我们的正式员工对待。我就在琢磨,难道是在暗示我再来会加薪,那敢情好!^_^

不罗嗦了,赶紧把论文整完。

SVN you should know

SVN 是 Subversion 的缩写,一个开源的版本管理工具,类似于 CVS 和 Visual Studio 的 Source Safe。不过据它的作者称是因为忍受不了 CVS 的缺点所写的,可能会比 CVS 表现好一点,因为我只有在 check out 某些开源代码时候才会用到 CVS,并不经常,所以只是猜测。不过肯定是比 Source Safe 表现要好,因为两者的理念是不同的,Visual Source Safe 管理小型项目还可以,是不适合管理多用户的大项目的,再说,Source Safe 也只能在 VS 里面用,而 SVN 的客户端有 Linux 和 Window 的版本。顺便提一下的是,WIN 下有种最流行的 SVN 客户端就是集成在右键菜单的一个小乌龟,很有意思的。

SVN 有非常好的使用文档,相比其它的开源项目来说,SVN 的中文化也做的很好,有专门的中文站,可以搜一下。SVN book 介绍的相当全面,但是,读完那么长的文档也没有必要。我这里就介绍一些常用且是最常用到的命令(Linux 下,Win 下就不说了,都是 GUI 操作)。

建立版本库:svnadmin create /data/svnpool
这是指定版本库存放的位置,貌似必须是一个绝对路径,建立好以后里面会建立起一些配置和数据库的文件。

指定编辑器:export EDITOR=vim
因为每次的版本操作都要添加一些信息在 log 里,把 EDITOR 放在环境变量里可以使用自己熟悉的编辑器来编辑这些信息。这句话经常放在 .bashrc 里。

导入项目:svn import file:///data/svnpool
在当前目录下的所有目录和文件都会导入到版本库里。

列表查询:svn list file:///data/svnpool
一般情况下都要先查询一下某个目录存在不存在才去导出。

导出项目:svn co file:///data/svnpool/project
这时候会在当前目录下建立一个 project 的目录,里面存有 SVN 的信息。

更新项目:svn update
使当前目录下的所有文件和目录版本与版本库中保持一致。

查看不同:svn diff
查看当前目录下的所有文件和目录与版本库中有那些不同,也可以加上版本参数 -r revision1:revision2 查看两个版本有什么不同。

添加文件和目录到当前项目:svn add subdir/file
把当前目录下的 subdir/file 添加到当前目录对应的项目中去。

删除、移动或复制当前项目中的目录和文件: svn rm/mv/cp ...
把某个文件或目录更改名字、复制或从版本库中删除。

提交更改:svn commit
把更改后的文件提交到版本库中形成新的版本。

在初始导出和导入的时候,可能需要给出 URL,主要有几种格式,file:///, http://, svn://, svn+ssh://user@host。当项目已经导出时候,就不需要打路径名了,有可能需要密码,如果验证的话。

这些是最常用的命令,像其它的一些命令,比如 merge 之类的,用到时候再查 svn book 和 man page 也不晚。版本控制很有用的,比如自己平常写的代码,放到版本库里就比较好查询和撤销修改,而不用每次都保存个备份。而且增量修改时当代码发生错误时候可以很快定位更改在哪里,找到错误原因。其实所有文档都可以放在 SVN 库里的,只是某些文件类型不好做 diff 罢了。

为 GDB 添加新的目标机 (3)

本文遵从 GNU Free Documentation License (see http://www.gnu.org/copyleft/fdl.html ),并特别对 冒充另类(TeaWater) 的《移植GDB》一文表示感谢 (see http://teawater.spaces.live.com )。由于大体和细节的东西在《GDB Internal》和《移植 GDB》两文中已经有了很多描述,所以本文的目的在于 Howto,step by step 地描述如何为 GDB 添加新的目标机,并对某些以上两文中阐释不清的地方做出自己的解释。

3. taget dependent 文件补充说明
其实关于 solrex-tdep.h, 和 solrex-tdep.c 文件中所涉及的函数, TeaWater 的《移植 GDB》一文讲得非常清晰,我也没必要重复,我只对一些他没提及的东西做一下解释。

(1) solrex-tdep.h 中应该放些什么

其实这个主要是根据需要,如果一些东西会被别的文件使用,那就放在这里,如果没有,这个文件甚至不需要。当然,一些应该放在头文件中的东西还是放这里比较好。

(2)关于 struct gdbarch_tdep

这个结构体是用户定义的,最重要的使用也是在这两个文件中。可以根据需要增减,一般的话需要几个:registers map,重要的 register number,然后就是 abi 的东西。只要用户觉得某个东西有用,就可以放在这个结构体里面。

(3)关于 pseudo registers

这个东西主要看编译器的实现,如果编译器就根本没有这些东西,没有必要处理这些东西。

(4)关于 unwind_pc

不要被它的名字迷惑,unwind_pc 所起到的作用原理很简单,返回一个位于(参数 next_frame 的上一层 frame)中的地址,一般情况下就是这个函数的返回地址。因为函数的返回地址一般就是对这个函数调用的汇编指令的下一个指令,GDB 内部会把这个返回地址再减去一个指令长度,这样就回到了函数调用那句话,函数调用肯定位于被调用的函数的上一个 frame 中。但是有两种情况你需要考虑,如果 next_frame 是一个 sentiniel frame, 只需要返回当前 pc 的位置,如果是一个 normal frame,就需要返回这个 frame 的函数返回地址。这个具体怎么做需要看特定的 target,比如 mips 很简单,只是把 pc 给它,但不是所有的 target 都是这样的。只需要看一下汇编代码就知道该怎么做了,一般情况下进入一个函数,首先是把移动 sp, 给这个函数留出一段栈地址,然后是把 ra 压栈。但是有时候也不完全这样,假如 ra 不是 GPR,不能直接存入栈中,只能先放到一个 GPR 中然后再把那个 GPR 压栈。

之所以要讲到上面的例子就是因为,GDB 的逻辑是这样的:告诉他要 unwind 哪个 register,它会先调用注册的 frame_prev_register 函数去找这个 register,很多情况下 target 都是先注册 dwarf2 的 dwarf2_frame_prev_register。这个函数会根据 debugging information 中的 FDE 和 CIE 去找这个 register 是放到哪里了,然后去那里找到这个 register 的值。但是这个函数有个缺陷就是,假如把一个 register 放入另一个 register 中,它只会到下一层的 frame 中去找那个 register,这样在上段说的最后一个例子,就会出现错误,因为被存入的 register 只是做一个中间值的用处,它会把自己压到栈中,而 dwarf2_frame_prev_register 到下一层的 frame 中去找它的值,显然不可能得到正确的结果。

(5)关于注册特定的 frame_unwind_append_sniffer 有没有用

在很多情况下,尤其是在 linux 的编译器都会为 ELF 文件加入 DWARF2 格式的 debugging information,所以很多情况下用户注册的 frame_sniffer 都是没有太大用处的,但是如果不注册也会发生问题。因为 GDB 中 DWALF2 的处理是先找 symbol 里对应于这个 pc, 有没有 FDE,如果有 FDE 就采用 dwarf2 的 frame sniffer,如果没有就采用用户另外注册的 frame sniffer。如果用户没有另外注册 frame sniffer 的时候,GDB 会出现 internal error,而当注册了以后,GDB 内部会在二进制文件中找这个 pc,如果找不到,会返回用户不知道现在位于什么位置。所以,当二进制文件中有 debugging information 时候,再注册特别的 frame sniffer 只是为了不出现 internal error。因为当 pc 正确时候,自然有 dwarf2 处理,当 pc 不正确的时候,GDB 也不会使用用户定义的 frame sniffer。用户定义的 frame sniffer 唯一有用的时候就是二进制文件中没有 debugging information,这样 GDB 会调用用户定义的 frame sniffer 来找 frame 的开始位置,栈分布和 register 的处理。

(6) gdbarch 中那么多东西,应该注册多少

我觉得,至少应该告诉 GDB 的是: info.byte_order, tdep, num_regs, sp_regnum, pc_regnum, stab_reg_to_regnum, dwarf2_reg_to_regnum, register_name, register_type, skip_prologue, inner_than, unwind_pc, call_dummy_location, unwind_dummy_id, push_dummy_call, print_registers_info, print_insn,然后再加上注册一下 frame_unwind_append_sniffer 和 frame_base_append_sniffer 就行了,剩下的就要看各个 target 的特性,需要不需要添加了。

唉,写了以后才发现自己没多少可写的,因为每个函数的用处 TeaWater 的《移植 GDB》中都讲到了,而要是真 step by step 地写,工作量也太大了点,算了,就这样吧,其实很多东西是只有到用的时候才知道哪里会出现问题的。不过用 GDB debug GDB 也是一件很有趣的事情。

Beryl is so cool

以前看到 SUSE 10.1 带的 beryl 效果,觉得非常有意思,但肯定会吃资源,就没想过尝试。自从那天看到同事的桌面也用了 beryl 之后,我才知道原来集成显卡也是可以安装滴。只可惜我的 SUSE 是 10.0,Qt 库的版本不够,只能望屏兴叹。昨天晚上下好了 Ubuntu 7.04, 叫什么 herd-3 测试版还是什么东西,我也记不住这种东西。心想,安上这个就可以玩 beryl 了。

测试版真的是很讨厌,我的 SATA 硬盘,WinC 盘是 FAT32 的,为什么把光盘镜像放在这个分区上就找不到呢?我差点想去改 initrd.gz 里面的寻找路径,还真从那里面让我找到了,但头痛的是,我不知道我改了后再压缩会不会识别不了。心想,算了,说不定是分区的问题,失败两次之后就学乖巧了些,拷贝到 ext3 格式的 linux 分区一个镜像,结果再找镜像就 OK 了。

但是安装时候还出了一个问题,我选择语言是中文,国家和地区是中国,它就是会停到安装 openoffice-java-commen 这个包上,真是奇怪了。只好选择语言英文,但是,但是,为什么我选择语言是英文不能选择国家和地区是中国呢?这是什么逻辑?没的办法只好选择香港。

安装好以后,彻底 upgrade 一番,这没出问题。但在安装中文支持的时候,最后一步说不能识别 zh locale。我郁闷了,一看,下载下来的中文支持包是 6.06 版本的,怪不得,那么久没有更新了。所以,现在我的 feisty 能正常显示中文了但不能输入,scim 能启动但就是没法换输入法,唉,忍了吧,谁让咱是中国人呢?中国博大精深的文字那些鬼佬们怎么能轻易而举地使用呢?

然后就是安 beryl,看网上教程看到头痛,丫的安一个软件这么费劲。我一怒,不管了,就把 ubuntu 的 beryl org 的源加到 source.list 里面,然后 wget 一下 key,直接 sudo apt-get update, sudo apt-get install beryl。我紧张地看着进程跑完,哈哈哈哈,居然没出问题,直接就能用。看来 Ubuntu 在这方面还是下了点功夫的。

我最喜欢 beryl 的就是桌面的转换,cool 啊,而且使用快捷键比原来 1234 桌面换来换去直接地多,也能在脑子里形成反射:恩,去左面的桌面,恩,去右面的桌面。而不用像以前一样老在想,该进几号桌面啊?

版上还有人评价 windows vista 和 beryl 达到同等效果所耗费的内存。虽然两个操作系统这么比没意思,但还是觉得 beryl 做的相当不错。

使用自由软件构建交叉编译、汇编和连接工具, Cross-build gcc for mips.

唉,好郁闷,做的东西自己都不懂多少。我 GDB 用的都不熟,还要给 GDB 添加新的 target。自定义 elf 文件的 BFD support, target dependent, disassembly function, 好几千行的代码啊,弄不好得上万行,GDB 那么多文件,看得我头都晕了。

因为我们的芯片和 MIPS 关系比较密切,就先编了个 MIPS 的交叉编译和调试环境玩玩。

Concepts:

交叉编译,就是在一个平台上生成另一个平台上的可执行代码。这里的平台包含两个概念:Architecture 和 OS,x86 Linux平台是Intel x86 arch 和Linux for x86 OS 的统称,Sparc SunOS 4.x 就是 Sparc arch 和 SunOS 4.x(or Solaris 1.x) 的统称。生成交叉编译器后就可以在主机上生成目标机的代码,就比如说显然低端手机上不可能装一个操作系统,更不用说编译器了,但手机上仍然需要安装软件才能提供服务。就需要使用交叉编译器,在 PC 上编译好程序以后将二进制文件装载到手机的内存中去(有可能直接烧进去,或者使用 bootloader 加载)。这个时候,PC 就是主机,手机就是目标机。这个程序在主机上是不可能直接运行的,因为它的代码指令是目标机的指令,很可能和主机的指令集完全不兼容(不然要交叉编译器干吗?)。

调试环境,程序编译成可执行文件之后肯定需要调试,但是代码在主机上无法运行,如何调试?常用的有几种办法:1.把二进制文件加载到目标机上,打印出调试变量。2.把二进制文件加载到目标机上,通过串口或者网口向管理程序交流,实现在线调试。3.把二进制文件放到主机的模拟器软件上运行,进行调试。其实还有一些其它的方法,比如 ICE(in-circuit emulator),但是代价比较高。这几种方法一般都是混合使用的,很难一种就完全满足要求,就连 Nokia 出的手机模拟器也是漏洞百出的,必须得在板子上运行之后才知道代码有没有错误。

GDB 是支持远程调试的,可以通过 serial port, tcp, udp 和 pipe 与目标机进行交流,使用的语言叫做 RSP(Remote Serial Protocol),同样这需要目标机使用同样的语言和它交流,这样就需要一个翻译。这个目标机上的翻译程序就是 stub(裸机和简单操作系统) 或者 gdbserver(可以运行gdb的操作系统)。但是光有这些还不行,因为 GDB 必须知道目标机的结构(寄存器,字长等等),二进制文件的格式(elf,pe,寄存器代号),操作指令才可以实现远程调试,不然它怎么知道寄存器名对应的是哪个?怎么加载函数的符号表来设置断点?怎么反汇编地址内容?唉,我现在要做的就是把这些添加到 GDB 中去,然后把 GDB 和模拟器用 RSP 连接起来。其实我们的模拟器就支持直接调试的,但是客户不一定喜欢字符界面啊,要做 IDE 的话,而且以后还要支持在线调试,还是用 GDB 方便,毕竟 GDB 可以和很多 IDE 集成。

Practice:

我们的编译器是改的 openCC,我也不懂。这里编的是GCC,它已经支持了很多平台,arm, mips, sparc, powerpc...,通用性更强些。

编译工具需要好几个部分,这就有个编译顺序问题,应该先编什么?显然应该从最底层编起,顺序大致应该是:

binutils, gcc-cross, library, gdb.

其实 GDB 无所谓了,放在什么时候编都一样。但 binutils 必须放在 gcc-cross 前面编(如果不能使用主机上的as, ar, ld, nm 这些二进制工具的话),而 lib 也得看需要不需要 gcc-cross,如果直接使用主机上的编译器编译的话,就放在前面编,如果不能使用,就放后面编。glibc 太大了,很多时候会使用其它的 lib 代替,比如 uclibc, newlib 等等,特别是目标机操作系统有要求时。

编译过程都不难,无非是 wget,tar,configure,make,make install。但是有很多情况下过程不会那么顺利,尤其当不了解整个工具链的要求时,碰到编译不过最好找个懂的人问问,是缺少 lib 啊,还是配置问题。

我用的版本都比较新,binutils-2.17,gcc-core-4.1.0,newlib-1.15.0,gdb-6.6,最重要的就是 configure 啦,随便写一下,编译最好在新建目录里。

/src/binutils-2.17/configure --prefix=/program --target=mips-elf
/src/gcc-core-4.1.0/configure --prefix=/program --target=mips-elf --with-newlib --enable-languages=c
/src/newlib-1.15.0/configure --prefix=/program --target=mips-elf
/src/gdb-6.6/configure --prefix=/program --target=mips-elf

要注意的是,如果编译 gcc-cross 时候加 --with-newlib 的话,要到主机编译器能找到的地方,比如对应的 lib 目录下建两个软连接,分别指向解压后的 newlib 根目录下的 newlib 和 libgloss,而且必须先编译出 gcc for mips-elf 后再编译 newlib for mips-elf。编译成功的 gcc 安装到 prefix/bin 目录后,会加上 mips-elf- 前缀。最好不要使用 --program-prefix 选项,这样会造成后续编译自动寻找工具的麻烦。最好将 prefix/bin export 到 PATH 里去。

其它还好,最头痛的是 gcc,时间很长,用 core 也得编10多分钟,还是在服务器上,配置也繁,比如 target 选 mips-linux-gnu 就是死活编不过去,选 xtensa-elf 也是编不过去,肯定是少什么或者设置不对,但就是不知道少的是什么,还是没有经验啊。要是再加上操作系统的东西,编译 gcc 前面还要先编 kernel headers, glibc headers,gcc 可能需要编两遍,还有 glibc, kernel,更麻烦。反正我现在至少不用费那个劲,现成的编译器已经有了,只是需要 map 一些东西到 gdb 而已。

GDB 自带 mips, arm 这些程序的模拟器,不知道功能怎么样,但至少可以用。但是编译时候的参数还有程序中函数入口等等实在是太烦了,写和调试嵌入式系统的代码那叫一痛苦。

Copyright © 2005-2007 Solrex Yang. All rights reserved.

宝贵的周末

又该周末了,非常开心。做学生不知道,周末和平日里差不多,现在才真切地感觉到周末对上班族来说是何等的幸福。看着坐办公室很舒服,坐一天不动弹没什么,但连着坐五天就知道有多痛苦了。真是感谢那些为我们争来8*5工作制的伟大的工人先驱们。

最近又买了几本书,"Introduction to Algorithms", "Internetworking with TCP/IP", "Exploring Expect",花了160多块。前两本在中关村书城买的,影印,8折。最后一本是在淘宝上找到,然后跑到北京中医药大学一美女那买的,第一次买翻印的原版书(就是DB啦)。写 expect 这个人太吝啬,documentation 没啥实质内容,满篇告诉你 exploring expect 有多好,然后推荐你去买,最可恨的是居然连电子版都找不到。要么你去买他的书,要么你忍受简陋的 man page,faint。而且因为太老,95年的,中国没有出版社引进,还好有人做好事。中国啥都缺,就是不缺盗版。

本来以为看原版书很痛苦,速度也慢。但在看文档时发现,工作压力逼着速度就快很多,该跳就跳,该扫就扫。阅读计划一大堆,Thinking in C++, More Effective C++ 电子版都在看,才读了十分之一,不知道何时能完成。反正这些书以后总会用到,就算看不完也当作工具书吧。

这个星期学到不少东西,还第一次用 mailing list 和别人交流,挺有意思的,也算是我开始为 GNU 的开源事业做贡献啦。估计下个星期就要开始实质的开发工作了,导师让我试着完成一个 command completion 的东东,就是用 tab 键补全命令,我们的 simulator 现在还不支持这个功能。开始 C&C++ 之旅了...........

发现最近日志数量明显增多,按我的规律这意味着最近日子过的很无聊,心情很郁闷。啥会儿我能戒掉写日志啊?

唉,该写完了发现用 vim 习惯到在 UltraEdit 里保存文件都开始令人发指的用 Esc :w 了,难道我要成为一个彻头彻尾的 Linuxer?

Copyright © 2005-2006 Solrex Yang. All rights reserved.

这天儿是越来越冷了

Google Desktop 说今儿温度是-3~3℃,在办公室感觉都不一样,脱了外套开始有些冷了。不过还是很喜欢北京滴,起码屋里还足够暖和。这天气甭管放在商丘还是放在南京,在房子里也要受不了了。到这个时节还没穿上毛裤,对我来说也是第一次,:),我妈要是看见了准该骂我。

公司的活是真不重,不然我不能经常有空写博客了。我做的是回归测试,基本上任务就是把别人写好的测试用例运行一下,然后 report。量是比较大,但反正都是脚本,也很 easy 。shell, tcl, expect 和 makefile 脚本编写渐入佳境。小脚本做大事情,真是体现了命令行功能的强大,在这点上 Windows 的 shell 和 *nix 的 shell 是没法比的。当然,我不是说 Windows shell 的不强大,只是相比而言。基本上我花在每个脚本上的时间不超过三四个小时,一天撑死两个,相当闲。呵呵,看来当初学 Linux 的工夫没白费。也真是,花了四年时间学的一钱不值,到头来挣工资用的却是四个月就能学到的东西。

公司里的人年龄都比较大,大部分比我大七八岁以上,二十五六的就没几个,只有我一个实习生。那天吃饭时我的“导师”还问我是不是少年班的,所以他们似乎觉得我还嫩,干不了什么活,也不给我分任务。而且也确实,做芯片底层开发不是那么容易的事,编译器、模拟器、信号处理什么乱七八糟的东西都要写。就是把测试脚本编写这块扔给我,但也没有全给。嘿嘿,我倒乐得清闲,没事时候就做做自己的事情,看看技术文章之类的,也挺滋润。比我暑假实习那家环境好多了,连个隔间都没有,还加班。这里只要完成你的任务,你想干吗干吗没人管你。

在北京也呆了十几天了,有几个让我对伟大祖国首都北京感到很不爽的地方:

1.进银行先“挂号”。

呵呵,请允许我老土一下,不过真是第一次见到。我拿到那号一看:您前面有41位顾客,请耐心等候。心刷的就凉了,这41个人我得等到猴年马月啊?当时就想走,后来想既然来了,怎么地也得见识一下不!坐下以后才发现,哦,这41的意思是不管什么业务,总共41个人在等。再看看有5个窗口呢,运用小学学的数学(大学老师教的至今没怎么用到过)计算一下,恩,不错不错,在平均状况下每个五分钟我也不用等到一个小时。安心许多,心里就开始感叹起来:首都就是好啊,排队都能坐着!

2.红绿灯摸不准

请再允许我老土一下,我还真没见过一条路上相反的两个方向,一个亮红灯,一个亮绿灯;我还搞不懂为什么同一个灯杆上,自行车亮绿灯而行人亮红灯;我还弄不明白的是为什么明明你面前横着的这条路上都是红灯而你对面的行人灯还是红滴。在南京,我在概率的意义上还算一个遵守交通规则的人,但是到北京我发现就算我很想遵守交通规则但是红绿灯搞的我忍无可忍,行人绿灯亮的时间仅足以你用最快的步速跨到对面,而且明显同一个方向上的机动车享受的绿灯时间比行人长得多。对此我很无语,我只能在珍爱我自己生命的前提下选择什么时候闯红灯。

3.公交系统极不人性化

为什么公交车的侧身不写多少路和经过的站点啊?白天还好点,凌晨和傍晚时候像我这种近视根本看不见车头的多少路,嗖一下就停我跟前了,我非得跑到车头看看是多少路再决定上不上车。为什么报站不报下站到哪儿啊?自动报站的公交,包括公交车和轨道交通,就没有报过下一站是哪里,相比而言有售票员报站的还好些。为什么地铁站没有售票机呀?上班高峰期得排老长的队。为什么地铁没有自动扶梯啊?上下太不方便了,尤其是带着东西时。

4.人行道上贴广告

在南京我从来没注意过人行道是什么样的,但在北京只要你稍微低低头,就会发现那种类似于名片大小的办假证之类的广告贴满了人行道和天桥,至少在我上班那条路上是这样。这里想给那些什么分众、聚众、分时传媒提个醒,千万别忽略了这N平方米的广告牌,N的数量级应该在千万以上。市政也可以小赚一笔呀!

不爽的地方还有,比如暂住证,我到现在还没办,不过打算办一个,主要是好奇。我将坚持一个月不办表明反对暂住证的立场,然后办一个满足我自己的好奇心 :)。这一个月不是确指,因为我实在不知道什么时候愿意把时间花在这上面。

现在有个小计划想研究一下怎么写 Google Desktop 的 Gadget,想做一个但又没好的想法,回去再想想吧。

以后要按时下班,按时吃饭,不在办公室熬夜了。反正都是玩,回去虽然连书都很少,无聊些,但对身体好一点,这两天在看《可怕的对称——现代物理学中美的探索》,要锻炼自己思维的能力,我们要勇于去探索自己未知的领域 :) 。周末打算去国家图书馆办张卡。
Copyright © 2005-2006 Solrex Yang. All rights reserved.

有趣的 Quine

quine [名字源于逻辑学家 Willard van Orman Quine, via Douglas Hofstadter] ,指的是一种运行后生成自身源代码拷贝的程序,也叫self-reproducing programs(自我复制程序)。今天无意中搜到 Ken Thompson 的一篇经典演讲 Reflections on Trusting Trust,好奇心下就小探索了一番。

answers.com 上有一个c语言的例子:

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}

运行之后直觉得好奇,为什么它能把自身源代码输出啊?想着可能是某种特技,结果在Linux下,在Win下编译反编译调试比较汇编代码,折腾了半天。到最后看发现实在太繁,还是静心读一下源代码吧,才发现,原来如此的简单:

printf中的第一个参数f,就是格式化字符串,34就是双引号的"ASCII码,10就是换行符的ASCII码,很显然f就是一个用它自身去格式化自身的字符串而已。技术看起来简单,但是要实现完全相同的代码输出,在编排上还真得下一番工夫。

Gtalk上碰见yutian,给他发了过去,还打赌他肯定看不出来运行结果,现在才发现自己幸亏没真赌上。:D,不过人那,还是感情的动物啊,都有一种习惯性思维,看到貌似复杂的东西自己就先限制住思路了,结果他也没看出来,哈哈。

看来,把复杂的事情搞简单,还真不是件容易的事儿。做人,还是简单点好,遇事想那么多干吗,给自己找烦恼。

PS:

谁要对 quine 还感兴趣,这里 有几乎所有语言的一种 quine 实现,这东东好象对写恶意代码很有用啊。
Copyright © 2005-2006 Solrex Yang. All rights reserved.

写在我的20岁

时间眨眼间又转了一个轮回,快得有点让人无法应酬,手足无措中我进入了生命中第21个年头。去年今日此博中,写下了对19岁中的期待,还有一点点小计划,看看这些计划执行的什么样子:

数学,三上那几门都是考的不错的,三下就有点差了,关键在泛函;英语,TOEFL考了,590,数学成绩也不太好,放弃出国的打算,GRE自然也丢掉了;计算机,C++就看了一些STL的东西,倒是对JAVA的观点发生彻底的转变,学了不少;金融学副修,三下时候只过了一门,不得已还是放弃了;Linux和服务器的东西看了一些,汇编语言也学了不少,暑假找了份工作,做了几天事。

综上,得证,我是一个没有执行力的人。Q.E.D.

或者可以找个开脱的说法,:),计划赶不上变化。

曾经做了个预言:所有的事情都在往好的方向发展,没有理由不高兴。如果通观全年的话,它还算是成立的,虽然其中不乏坎坷,但坎坷未尝不是一种幸福!

在20岁生日,要感谢老天对我这一年的眷待,感谢给我那么多不曾敢奢望的幸运,也要感谢兄弟姐妹们给我那么多的鼓励和支持,我真的非常非常感激。

站在这个点上向前向后看,我看到的是充实幸运的过去一年,但仍看不清前方会是什么样子。我不敢奢求老天再给我几分运气,不过我会努力去争取。在每一个 lucky dog 背后,都有他不为人知的努力,这点想与正在忙碌着考研、出国、找工作的兄弟们共勉,只要努力,不怕没有好结果。重新跋涉的路途遥远,你还要自己保重,就在你最感疲惫的那一分钟,会听到胜利的号声。我在高考誓师大会上的演讲引用过这句歌词,没想到前几天居然还有外班同学提到,现在看来,这句话很有道理。

明天就要离开南京了,先回趟家,然后去北京实习半年。要离开自己熟悉的校园环境,真有点百感交集,不知道是何种心情,总之,该面对的还是要面对。想起几个好友经常扯:“要走贤惠路线了”,看来我也“要走成熟路线了”,^_^。

PS:

走之前做件好事,因为咱年级的出国代理是我和yutian开的,我把代理脚本重写了一下,还简化了代理配置的步骤,现在只需运行一个文件就可以更改IE和Firefox的代理设置了,写了一点帮助文件,和两个比较有用的脚本打了一个包,放到我个人主页上了,也可以点击这里直接下载。对那些不懂电脑的同学可以说是近似傻瓜配置了,也算是方便大家吧。有兴趣琢磨的同学可以看一下原理,全是脚本和批处理文件,非常简单的。

PSS:

班务的事情我在百合上发贴了,大家看到了相互转告一下。

Copyright © 2005-2006 Solrex Yang. All rights reserved.

Sun’s Open-sourcing

继11月2日的 Microsoft-Novell Deal 的又一件开源软件界大事: 11月12日,Sun Microsystem 总算在几年的观望后决定把 Java 开放源代码了,而且选择了 GPL ( general public licence ) 协议,更进一步的是,今天(14日) Sun 又在它的 Glassfish ( its open source Java EE application server ) 加入了 GPL 作为候选 licence, 这样开发者就可以从 CDDL( Common Development and Distribution Licence ) 和 GPL 中选择自己需要的一个了。看来 Sun 是要专心在开源这条路上走下去了,有评论说:“A similar scenario could be a likely future for Solaris. ”,想来也不是没可能。

其实 Sun CEO Jonathan Schwartz 11月3号在自己的博客里就说了 On the latter(open source landscape), from where I sit, we’re seeing an increasing schism in the market, separating those that protect their customers at the expense of the open source community, from those that protect the community while leaving customers vulnerable. Our view is you have to respect both, and that we’ve effectively threaded the needle with both OpenSolaris and OpenSPARC, and Sun’s commercial derivatives of both - and that those best practices will guide our approach going forward. If you want proof, stay tuned for next week’s announcements. (It won’t be a boring week.) 这个星期确实不是一个 boring 的 week。不过有意思的是,这个声明正好比 Microsoft 和 Novell 的条约缔结晚一天,不知道是不是 Sun 看到微软和 Linux 阵营的靠近心生不安了,才加快了它的开源步伐。这样它能更多的得到 Linux 社区的支持和拥护,因为 Java 如果采用了 GPL 协议的话,估计在每个 Linux 发行版的下一个版本里都会把它作为一个标准配置,或者至少是可选的配置。呵呵,其实对我来说可能这一点才是最重要的,:),这样就不用自己再去下载 JDK 了。

对于 Java 语言我是非常喜欢的,它的开源我也是非常希望看到的,这样我就会有更优秀的语言和更强大的库使用了。不过还是希望 Sun 能够维护一个业内比较强大的标准,避免像 Linux 那样慢慢地走上分歧的道路。至于 Java 的开源对软件业以及计算机语言发展的影响,自然有很多专家去评论,我没有那个前瞻性。

在这个事件里还能看到的比较有趣的一点是 Sun 对 GPL 协议观点的转变,去年它把 Solaris 开源的时候选择的是 CDDL 协议,当时它对关于其选择 CDDL 批评的回击是 the GPL was unfair and predatory because it requires developers to publish changes to the source code. Schwartz(当时是COO)说: the GPL was unfairly used as a way force developers to share their work because the creators have a hidden agenda of forcing a social model on the world. 才过去18个月,Sun 就改变了它对 GPL 协议的观点,看来没有什么是不可以改变的,就连微软都能和 Linux 走到一起,Sun 的观点转变也不算太过。

不过正如有人说过 Sun 的开源一般都是在压力下才达成的,Solaris 是因为服务器市场份额的急剧下降,SPARC 也是因为在处理器市场的不得志,NetBeans 是因为 Eclipse 吃掉了其大量的用户,Sun 究竟还能在开源的道路上走多久,就得看它到底把自己的盈利模式定义在什么位置上了。没有公司愿意赔本做开源,尤其像 Sun, IBM, Microsoft 这样的大公司。开源软件不是福利事业,和赚钱并不矛盾。其实开源软件真正想发展壮大,就必须得找到一个好的盈利模式,这样才能形成良性循环,不然一个个公司的破产肯定会给开源事业造成打击。开源事业需要社区的努力,也需要这些厂商的鼎立支持。看来要订阅 Jonathan 的博客了,要看看他今年能折腾出来多少东西。

Copyright © 2005-2006 Solrex Yang. All rights reserved.

Ubuntu is so cool

上次用Breezy,还没有体验到Ubuntu的好处,这次装上Dapper,才发现Ubuntu用起来那么爽,真是很酷,怨不得有那么多FANS。

1.免费的光盘派送

虽然说这个不是起决定作用,但是能有正版的无差错的安装光盘,谁愿意去下载那些很难保证质量的光盘镜像呀,就像上次下的FedoraCore5,更新安装时候还好,起码剩个系统用,全新安装时候根本无法成功安装。

2.方便的软件安装,丰富的更新源

这也是那么多人喜欢Debian的原因,可以很方便的管理软件,而且,apt-get命令简化了很多麻烦的操作,避免了编译软件包或者直接安装时候出来的某个某个库找不到的罗嗦,直接apt-get就能把所有需要安装的部分自动下载安装好。况且,Ubuntu的更新源也很多,国内国外教育网都有,速度也还可以。

3.全面的使用和配置文档,尤其是中文文档

Ubuntu Wiki涵盖的范围非常广泛,包含了许多可能遇到的问题和解决方案,尤其是中文方面,比其他版本的要好很多,遇到问题再也不用Google半天了。

4.简单快速的系统

显然,只有一张CD,安装速度也很快,半个小时左右,比起5张CD的FC5,4张CD的RedFlag,DVD的SUSE是方便多了。启动速度也很快,配置好以后启动不超过1分钟。简单并不代表不好,基本功能已经很全了,需要什么更多的软件apt-get一下就行。而且桌面也很漂亮,GNOME桌面能做成这个效果,真的很不错了。

总之,作为桌面使用来说,Ubuntu绝对是相当相当的优秀。到现在为止发现它唯一不爽的地方就是,它不带金山词霸,这也是垃圾RedFlag为数不多能让我赞一下的地方:),BTW,RedFlag自带的应用软件真的是很丰富。

P.S. 贴一下速度比较快的源,sources.list For Dapper(6.06),系统自带的那些个不是很好,比较难连上,速度也不行。
# http://www.ubuntulinux.nl/source-o-matic
#
# If you get errors about missing keys, lookup the key in this file
# and run these commands (replace KEY with the key number)
#
# gpg --keyserver subkeys.pgp.net --recv KEY
# gpg --export --armor KEY | sudo apt-key add -

# Ubuntu supported packages (packages, GPG key: 437D05B5)
deb http://de.archive.ubuntu.com/ubuntu dapper main restricted
deb http://de.archive.ubuntu.com/ubuntu dapper-updates main restricted
deb http://security.ubuntu.com/ubuntu dapper-security main restricted universe multiverse

# Ubuntu community supported packages (packages, GPG key: 437D05B5)
deb http://de.archive.ubuntu.com/ubuntu dapper universe multiverse
deb http://de.archive.ubuntu.com/ubuntu dapper-updates universe multiverse

# CN99
deb http://ubuntu.cn99.com/ubuntu/ dapper main restricted universe multiverse
deb http://ubuntu.cn99.com/ubuntu/ dapper-updates main restricted universe multiverse
deb http://ubuntu.cn99.com/ubuntu/ dapper-security main restricted universe multiverse
deb http://ubuntu.cn99.com/ubuntu/ dapper-backports main restricted universe multiverse
deb http://ubuntu.cn99.com/ubuntu-cn/ dapper main restricted universe multiverse

# LUPA浙江
deb http://mirror.lupaworld.com/ubuntu/archive/ dapper main restricted universe multiverse
deb http://mirror.lupaworld.com/ubuntu/archive/ dapper-security main restricted universe multiverse
deb http://mirror.lupaworld.com/ubuntu/archive/ dapper-updates main restricted universe multiverse
deb http://mirror.lupaworld.com/ubuntu/archive/ dapper-backports main restricted universe multiverse
deb http://mirror.lupaworld.com/ubuntu/ubuntu-cn/ dapper main restricted universe multiverse

# Ubuntu官方
deb http://archive.ubuntu.com/ubuntu/ dapper main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu/ dapper-security main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu/ dapper-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu/ dapper-backports main restricted universe multiverse
deb http://ubuntu.cn99.com/ubuntu-cn/ dapper main restricted universe multiverse

# 上海交通大学
# deb http://ftp.sjtu.edu.cn/ubuntu/ dapper main multiverse restricted universe
# deb http://ftp.sjtu.edu.cn/ubuntu/ dapper-backports main multiverse restricted universe
# deb http://ftp.sjtu.edu.cn/ubuntu/ dapper-proposed main multiverse restricted universe
# deb http://ftp.sjtu.edu.cn/ubuntu/ dapper-security main multiverse restricted universe
# deb http://ftp.sjtu.edu.cn/ubuntu/ dapper-updates main multiverse restricted universe
# deb http://ftp.sjtu.edu.cn/ubuntu-cn/ dapper bleeding main multiverse restricted universe

# 清华大学
# deb http://mirror.net9.org/ubuntu/ dapper main multiverse restricted universe
# deb http://mirror.net9.org/ubuntu/ dapper-backports main multiverse restricted universe
# deb http://mirror.net9.org/ubuntu/ dapper-proposed main multiverse restricted universe
# deb http://mirror.net9.org/ubuntu/ dapper-security main multiverse restricted universe
# deb http://mirror.net9.org/ubuntu/ dapper-updates main multiverse restricted universe
# deb http://mirror.net9.org/ubuntu-cn/ dapper main multiverse restricted universe

Copyright © 2005-2006 Solrex Yang. All rights reserved.