人大脑的记忆能力是有限的。 我平时鼓捣电脑经常会遇到很多问题,解决后就忘记了,但如果下次再遇到,就又要求助于google从而浪费很多时间。网上很多知识技巧不值得去花时间记忆,建立一个知识库来保存这些技巧知识是最好的方法。TL上面大家关于如何建立自己的个人知识管理系统给出了许多方案。没有什么是最好的,只有最适合自己的。我曾经尝试过利用书签,自建wiki站点,Evernote,Dropbox等来建立知识库。但是始终觉得不够方便便捷。经过多次尝试,我最终选择了Zim wiki结合github和Dropbox来建立我的个人知识管理系统。

Zim wiki(http://zim-wiki.org/)是一个跨平台的个人wiki软件,其linux版本非常好用,没有Evernote那些花哨不实的功能,呼出速度也很快,适合从网页或者终端中保存文字。用来作为简单的个人知识管理最合适不过。 但是Zim wiki缺少同步功能,所以我通过设置github来为其添加了这个功能。因为zimwiki中每个条目都是一个txt纯文档,所以只需要在平时使用的Notebook对应的目录下面设置git,就可以把内容同步到github上面。之后只需要再把git pull和git push这几个命令写成一个bash脚本,就可以实现自动同步了。

#syncwiki.sh
cd ~/knowledge
git pull origin master
git add *
git commit -m "new"
git push origin master

为了更加方便,我又修改了下/usr/bin下面的zim程序,在

except KeyboardInterrupt: # e.g. <ctrl>C while --server
	print >>sys.stderr, 'Interrupt'
	sys.exit(1)

中sys.exit(1)前面添加了

	os.popen("sh ~/syncwiki.sh")

并将新程序保存为zimm,这样通过zimm打开的zimwiki在每次关闭wiki前就会自动与github同步了。你也可以通过添加crontab来设定定时同步。 使用github可以实现不同linux主机间wiki系统的同步,而linux与windows系统之间的同步我选择了dropbox。 Dropbox同步方法非常简单,将linux下面notebook对应的文件夹用ln命令做个链接,链接到Dropbox下面,之后在windows系统下面,设置zimwiki打开Dropbox的文件夹就可以。这种同步方法的缺点是每次修改后再次从另外一个系统打开zimwiki的时候会卡上几秒钟,而且如果两个系统同时修改wiki则会造成冲突,从而导致同步失败。 虽然存在不足,但是其实一般工作的时候很少会linux和win系统同时去添加wiki。还是那句话,够用就好。

除了使用github,你也可以使用其他的在线版本控制系统来实现wiki的同步。比如新浪的SAE。如果需要将自己的个人知识管理系统共享给别人,可以直接使用zimwiki提供的httpserver,直接共享成为网页。如果需要长期共享,可以去搜索zim wiki deploy(作者的blog:blog github地址:GitHub),这个人提供了将zimwiki转换为dokuwiki的脚本。

除此之外,你也可以尝试使用ssh -X来远程启动zimwiki实现同步:)

深秋的匹兹堡又是好久没有写blog了。这学期一直在实验室忙来忙去,但也没有什么成果。学业其实很轻松,于是每天的生活简化为家和学校两点一线,时间长了,人也就跟着变得懒了起来。这次的匹兹堡之行因为要参加在那里举办的IASTED(International Association of Science and Technology for Development)会议,因为如果不去参会演讲则之前被会议接收的论文就不能被发表,所以这才成行。

幸运的是,我在匹兹堡的这几天天气奇好,温暖的秋日阳光和碧蓝洁净的天空让人心胸也变得开阔起来。现在已是深秋,街边、公园里的树叶染上了金灿灿的黄色,风一吹,叶子就零零散散的落了下来,发出清脆的“沙沙”声。停下脚步,周围的美景让我觉得时间仿佛停止了。

其实我对匹兹堡的第一印象不是很好。那时刚从Megabus长途汽车上下来,背着登山时用的大包,茫然的望着一个陌生的城市。来美一年了,零零散散倒也去了美国不少城市,但是这次却是第一次一个人出发旅行。出发之前查了下google地图,发现从匹兹堡downtown的车站到我订的旅店要有50多分钟的路程。当时觉得50多分钟也没什么大不了的,结果走了20多分钟肩膀就被后面死沉的大包给压的生疼。从匹兹堡的市区往旅店的路是越走越荒凉,一下车周边还是高楼大厦,走着走着就变成了破旧的公寓楼房。再走一段,就看到野生的浣熊从周围的草地上钻到了一个废弃的水管里。当时我就庆幸自己之前没有贪便宜订晚上11点的车票,不然要是有个黑兄弟在路上突然闪出管我借手机借钱的话....伴随着夕阳落下,我最终顺利走到了旅店,一路上都是破旧的建筑和小巷,算是我对匹兹堡的第一印象。

第二天我一大早就起来去会场签到。进到会场,先到的人已经自觉地排了一个长队,一个个都是正装出席,唯独我是一身休闲装扮,与周围环境显得格格不入。签完领取完材料后,我本打算老老实实听场报告,结果等了10多分钟被告知要推迟半个小时,于是直接闪人。出来会场后时间尚早,我就计划去周围转转。

一开始我的目的地卡内基梅隆博物馆其实就在匹兹堡大学的旁边,匹兹堡大学虽然不如卡内基梅隆大学那么有名,但是校区建筑却非常漂亮,配合着深秋的红叶和温暖的朝阳,则变得更加迷人。值得一提的是匹兹堡大学的Cathedral of Learning,是世界上第二高的教学楼。这座建于1921年的高达42层的教学楼,至今还在使用着。已经成为了匹兹堡的地标。

到了博物馆后发现周一闭馆,于是只好改变计划前往卡内基梅隆大学。卡内基梅隆大学的CS专业排名很靠前,很多研究成果位于全球前列。不过这个学校校园并不大,整个校园色彩比较单一,感觉并没有想象中的那么漂亮。有趣的是在移动机器人实验室的楼下放着两个无线传感器节点,貌似是进行水分数据采集的,盒子上还印有一个大大的二维码,可惜估计是学校内网,我用手机扫描后没法访问这个网站。

在卡内基梅隆大学简单转了一下后,就出了这个校园,出来后突然想到应该去学校的礼品店买一件纪念品T恤。于是准备掉头往回走,但就在这时,我发现就在前面不远处有一栋非常漂亮的建筑物,很像是伊斯兰风情的宫殿。走近一看,发现原来是一座植物馆,叫做Phipps conservatory,回去查了下维基百科才知道,这又是一座有着一百多年历史的建筑物,始建于1893年。进到植物馆大厅,头顶是类似玻璃的结构,阳光从头顶的穹顶上洒下来。心情顿时大好,直接掏钱买票上楼开始一场计划外的植物馆之行。

这个植物馆除了有一般的植物温室以外,还有很多温室主题花园,这些主题花园都是围绕着一个特定主题来选择花卉和陪衬以及装饰物。例如去年新建的兰花馆,里面就都是由各种热带兰花组成,各种花卉的布置非常考究,与周边环境融为一体。还有一个日本花园,和一般的温室花园不同,它建在室外。花园里面的枫叶已经被深秋所染红,开始凋谢,可能是深秋最后的温暖的阳光照在我的身上,有那么一瞬间,你很难相信这个美丽的景色就在你的眼前,就在昨日心中印象还是破旧小县城的匹兹堡。

在植物园逛了大概有几个小时后就到了中午了。出来后便开始找吃的地方,路上经过了Schenley公园的Flagstaff Hill,整个山坡上出了一个练瑜伽的女子没有其他的人,公园里的树叶染上了金灿灿的黄色,风一吹,叶子就零零散散的落了下来,发出清脆的“沙沙”声。停下脚步,周围的美景让我觉得时间仿佛停止了。

之后我从公园再次回到卡内基梅隆大学,将整个学校的另外一半边逛了一遍。去Lulu's Noodle吃了午饭,到街旁的Caliban book shop买了一本书,就回到了旅店。开始准备明天的演讲和周五的考试。

第三天的主要任务是下午的演讲。上午我一直待在酒店准备演讲的PPT,因为这是第一次在学术会议上演讲,而且是要用英文演讲,所以要多花些时间和精力准备充分些。下午3点我前往了会场,3点半演讲正式开始。来美一年掐指算来也已经上台讲过6次,对英文演讲已经不在陌生。这次上台演讲因为准备充分,最后讲的也很不错。在接到组委会在演讲完毕递给我的证明后,我这次行程的最重要任务就算是圆满完成了。

第四天一早我就办了退房手续,背着大包前往卡内基梅隆博物馆。这个博物馆分为自然历史和艺术两个部分,因为时间有限,我就只逛了我最喜欢的自然历史部分。整个博物馆一共有三层,第一层主要是史前生物和地质矿石的展示,这些在之前去华盛顿DC的自然历史博物馆已经看过一遍了,草草掠过。第二层是美洲动物的标本,里面从棕熊到麝鼠再到海象海狮,各种动物应有尽有。同时每个标本展示框大多还都布置好相应的自然环境,非常好看。第三层有个个人收藏的展品室,里面摆了一架子的两栖爬行动物标本,青蛙蝾螈和各种蛇类乌龟都泡在一个个罐子里,初看有点吓人。博物馆里面除了我,还有一大群美国的初高中学生,貌似是来这里参观学习的。这些学生都是二十几个一组,由一个老师带队,然后由博物馆的相关人员对展品做讲解。除了这些学生,还有4、5岁的小孩子在博物馆的幼儿区,由博物馆的工作人员照顾讲解。联想到上次去DC的自然历史博物馆也是有很多学生拿着作业在博物馆参观,不由感叹,美国的私立学校的基础教育质量确实不错。

除了博物馆后我找到公交车,从博物馆直接坐到了downtown的长途汽车站。途中遇到了看我只有整钱没有零钱,于是帮我等人找钱的好心的司机。怕我下车后找不到长途汽车站,于是亲自带我到长途汽车站的美女Debra。

之后的故事就简单了,在经过了长途汽车,地铁,校车各种交通工具转换后,我最后从学校的停车场开车回到了家。结束了这次愉快的匹兹堡之行。

Greed is never good. - Linus Torvalds

下一版本的操作系统已经制作好,但是我在后续的开发上面遇到了困难(移植bash和gcc),我正在抓紧时间解决问题。等我先把需要学习的东西看懂并把手头的问题解决了,再继续发布教程。 另外,最近买了一个das的青轴机械键盘,非常不错:)

我们需要做的第一件事是在自己的电脑上搭建一个操作系统的开发环境。然后写个能显示"Hello World"的操作系统。

下面是我们需要准备的东西: 1、一个你操作熟练的编辑器,比如Vim 2、编辑C语言代码的gcc和binutils 3、用于自动化编译和链接的GNU Make 4、一个用于运行我们的操作系统的虚拟机,推荐使用Bochs。

安装上面的软件非常容易。在我的archlinux系统上面只需要一行命令

yaourt -S vim gcc binutils make bochs

就瞬间全部搞定了。 Ubuntu和Fedora系统安装这些工具应该也非常容易,如果有问题,大家自己用百度Google下就行了。 都安装好后,我们就要分析下下面需要做的事情了。我们已经有了Bochs作为虚拟机,而这个虚拟机可以通过模拟插入软盘或硬盘然后引导启动。我们可以把Bochs看作是一台电脑——事实上我们真的可以用一台电脑来代替它,只是在一开始的阶段,使用Bochs更方便于开发调试。 有了“电脑“后我们需要开发的第一个东西就是启动引导程序(Boot Loader),也就是让电脑在通电后通过引导程序运行我们的操作系统。但是这个Boot Loader的开发非常复杂,需要用到大量汇编知识。在这里我要介绍下UIUC的SigOps uBoot System。 这个uBoot系统是我们初学者的一个神器,它可以让你跳过令人头疼的Boot Loader的开发,而直接进入到下一阶段。它的用法很简单,使用一个bootmaker程序编译elf或者是其它文件然后创建一个SBBB (SigOps Bitchin' Boot Block 哈哈)的启动映像。然后我们就可以利用我们的Bochs来运行这个SBBB的启动映像了——这实在是太强大的一个工具了! 下面我来叙述下过程。 首先下载下面的文件

http://os-quake.googlecode.com/files/kernel_0_0_f.tar.gz

解压后我们看到里面有8个文件。其中main.c是我们写的"hello world"的主程序,bloader.h是对应的头文件,Makefile是对应的make文件,helloworld.ini是配置文件。bochsrc是我们所用的虚拟机bochs的配置文件,bootmaker我之前介绍过了。kernel.elf和helloworld.img是我们编译时才会生成的文件,我刚刚打包的时候一并打包进去了,你可以删掉然后让它重新生成。 再进行下一步之前,我们先熟悉下这些文件。首先看下main.c

#include "bloader.h"
int main();

/*Global Variables BAD BAD:) */
unsigned int oldEBP;
struct boot_dir *viewableDirectory;
int totalMem;
char * passedParams;
/*end global vars */

void _start(int memSize, char *parms, struct boot_dir *loadedfiles)
{
	asm("mov %%ebp, %0":"=m"(oldEBP));
	viewableDirectory = loadedfiles; /*make file mem locations global*/
	totalMem = memSize; /*make mem of system global*/
	passedParams = parms; /*make paramaters passed to system global*/
	main();

	asm("hlt");		/* this halts the machine, solving the problem of triple-faults on 
							some machines, but also making it impossible to return to DOS */
}

int main()
{
	char *vidmem = (char *) 0xb8000;
	
	/* "Hello " */
	vidmem[0] = 'H';
	vidmem[1] = 0x7;
	vidmem[2] = 'H';
	vidmem[3] = 0x7;
	vidmem[4] = 'e';
	vidmem[5] = 0x7;
	vidmem[6] = 'l';
	vidmem[7] = 0x7;
	vidmem[8] = 'l';
	vidmem[9] = 0x7;
	vidmem[10] = 'o';
	vidmem[11] = 0x7;

	/* "World " */
	vidmem[12] = 'W';
	vidmem[13] = 0x7;
	vidmem[14] = 'o';
	vidmem[15] = 0x7;
	vidmem[16] = 'r';
	vidmem[17] = 0x7;
	vidmem[18] = 'l';
	vidmem[19] = 0x7;
	vidmem[20] = 'd';
	vidmem[21] = 0x7;
	vidmem[22] = ' ';
	vidmem[23] = 0x7;

	/* "OS" */
	vidmem[24] = 'O';
	vidmem[25] = 0x7;
	vidmem[26] = 'S';
	vidmem[27] = 0x7;

	return 0;
}

main.c只有60多行,仔细看下。void start()应该就是我们的C程序和SigOps提供的bootloader之间的桥接函数,也就是我们使用bootmaker为我们的程序添加bootloader外壳时,它会让我们的程序从start()开始运行。事实上,实现这一点并不难。 我们可以通过类似下面的代码来实现一个类似的内核的main函数,并实现汇编和C之间的链接。 kernel_asm.asm

[bits 32] ; hey, we're in PMode

[global start]
[extern _kernel_main] ; always add a "_" in front of a C function to call it

start:
  call _kernel_main
  jmp $ ; halt

kernel_c.c

kernel_main()
{
     k_init();
     k_sayhello();
     ...
};

void _start()函数一开始做了一些初始化的工作,然后就直接跳转到main()函数。char vidmem = (char )0xb8000是CGA显示卡显示内存的地址(确切来说是 0XB800-0XBC00),一般的IBM PC在这一部分使用了统一编址的方式。因此若要让一个彩色字符显示在屏幕上,我们可以直接使用内存操作指令往这个内存区域执行写操作即可。0x7是一个控制字符,它用来设置字体的颜色为黑底白字。你可以查阅相关资料把它替换为其它颜色。(相关资料见 《Linux 内核完全剖析--基于0.12内核》 赵炯编著 机械工业出版社 2009.1 第24页 2.4.6 “显示控制”一节) Makefile没什么稀奇的,调用gcc把main.c编译为main.o 然后调用bootmaker读取helloworld.ini中的配置文件,bootloader生成一个包含bootloader的kernel.elf,然后利用ld命令把main.o和kernel.elf链接到一起生成helloworld.img。

好了,在了解了我们的程序之后,我们需要做的就是启动bochs虚拟机加载helloworld.img这个映像文件,然后启动。 下面是我们动手操作下,先输入命令make,生成helloworld.img映像文件,然后再用bochs加载它。

$ make $ bochs -f bochsrc

之后我们根据提示一路回车就可以看到我们的"Hello world"了! 就在屏幕的左上方,仔细找下 :)

如果运行起来有问题的话,请检查下虚拟机的配置文件里面的内容是否正确。确保里面romimage和varomimage的目录确实在对应的目录下。

好了,我们的"hello world"已经完成了。下面我们需要做的是要为它添加一些基础的功能,比如初学者最喜欢的printf()。

本系列文章旨在一步步指导读者完成一个操作系统的编写。不同于于渊大牛的《Orange's 一个操作系统的实现》,本系列文章将直接用C语言开始编写自己的内核,略过较为艰涩的汇编内容。因为作者我也是第一次尝试编写内核,所以文章中的错误应该不少,希望大家能够及时留言指正。

本系列文章使用的UIUC的SIGOPS代码。先向UIUC的大牛们致敬!

- 前言: 能够自己动手写一个操作系统是很多编程爱好者的梦想。不过,我们不得不承认,编写操作系统还是要比编写日常的程序要困难一些。因为这次你所编写的是操作系统,而这个系统要能够运行别人编写的日常程序。一个操作系统的创建,是一个白手起家的过程,你除了硬件和对应的手册,其他什么都没有。在我们操作系统开发的初期,我们会面临缺乏各种常用库,调试器和各种常用代码的窘境。好在现在我们有了互联网,网上丰富的资料把一切都变得简单了。

所需知识和设备: C or C++的语法知识 对计算机体系结构的了解,了解汇编语言。因为我们使用了SigOPS,而它已经提供了一个i386的结构,所以读者不需要一上来就陷入到汇编和计算机体系结构的细节当中去。我们会在后面根据需要逐步介绍。 一台装了Linux的机器:我只喜欢使用Linux。 坚持坚持坚持坚持坚持坚持坚持坚持

最终目标: 我希望在系列教程的最后,我们能够完成一个非常NX的操作系统。虽然在写下这段文字的我还没有达到这一目标,但是我会不断努力的。 我所说的NX的操作系统至少要具备: 能运行多个程序 能够有进程调度程序 有系统调用 有硬件中断....等等

好了 坑已经挖好了。下面开始动工!