Tuesday, May 5, 2009

Rainmeter Milestone!

修正了 ROUNDLINE 绘制的问题,现在 ToHeart2 的表盘能够很好的绘制了。

之前绘制的时候,时针和分针的长度一样,而且时针的位置不正确。查了半天代码,估计是因为某处没有用浮点运算,于是整型运算导致有较大的误差。

这两天又添加了一些皮肤,正在进行测试中。这个 Screenlet 已经基本能够正常使用了,就算作一个 Milestone 吧。

Saturday, May 2, 2009

Rainmeter 移植初步完成

昨天完成了类似 Rainmeter 的基本布局功能,加上今天的奋战,现在初步的移植工作已经基本完成,已经达到了我预期的目标。一开始只希望 ToHeart2 的那个主题能够在 Linux Screenlets 下运行的,现在除了这套主题之外,另外的几个主题也都能够正确运行了,挺让人开心的:


我觉得运行的效果还不错,和 Rainmeter 看不出区别来。目前除去 ToHeart2 的这套主题之外,我另外还在测试 2 个时钟主题,就是图中的两个时钟。今天努力了一整天,算是把基本的 Rainmeter 模拟工作给搞定了。不过目前还只做了 TimeMeasure 和 CalcMeasure,还需要添加新的 Measure,以及新的 Meter。今天实现 RotateMeter 花了我不少时间,因为 Rainmeter 的实现方式于我料想的区别太大,花了很长时间才找到解决反感。我总感觉 Rainmeter 对 RotateMeter 的实现方式有点诡异,很难以理解。不管了,既然我做的是 Adapter,那么就要能够完全模仿才行,即使诡异也好。接下来几天就抽空实现一下其他的功能,比如添加硬盘空间检测、内存检测什么的,最难的部分已经解决了,剩下的工作应该比较轻松。做到能支持20~30个主题我觉得应该就可以算成品了,可以上传到 Screenlets 官网上,顺便在 Rainmeter 论坛上做点小广告。此外还得继续用心做我的毕设了……

感觉 Python + Cairo 用来画图挺好用的,值得好好学习一下。Cairo 库真的挺强大的,而且上手容易,文档齐全,我觉得实用性应该和 GDK+ 不相上下吧。

Friday, May 1, 2009

开始做 Rainmeter 的 Linux 移植

Rainmeter 是我非常喜欢的一个桌面小程序,它可以监控 CPU、内存等的使用量,并且在漂亮的界面上展现出来。Rainmeter 最为成功的一点在于,它提供了很好的自定义功能,有很方便的 API 用于创建个性化的界面。我最初就是被它的一个漂亮界面(ToHeart2主题)给吸引住的,然后就一直使用到了现在,已经有 2 年以上了吧。这个软件的作者还开发了另一个同样美观实用的桌面程序 Rainlendar ,并且同时提供了 Windows 和 Linux 的版本。可惜的是 Rainmeter 目前的开发似乎已经停止(保持0.14版本已经相当长时间),并且没有提供 Linux 版本。

不过 Linux 下也有类似的桌面程序,我目前就在使用 Screenlets。这是一个利用 Python + GTK 实现的小程序框架,有一些挺实用的小工具,并且还有一些实例。其实以前就想试着做一个 Screenlet 出来,但是对 Python 的掌握还不到家,没有能力实现。最近稍微多接触了一些相关的资料,觉得可以试着做做看。细心看了 Screenlets 自带的 Example 源代码之后,算是大致有了了解,知道该怎样做了。此外还得看点 cairo 的资料,因为 cairo 是 Screenlets 的绘图引擎。在 DevHelp 工具中有相当详细的文档,基本上需要的资料都可以查到,因此就没有太大的困难了。

Rainmeter 最难实现的部分就是它对于配置文件的解析,这相当于要写个解释器。Python 本身提供了一个 ConfigParser,专门用于解析 ini 文件,有一定的帮助作用,免去了做文本分析的工作。不过麻烦的是配置文件的逻辑,这个解析起来有一定难度。Rainmeter 配置脚本里主要有 4 类信息:基本配置,Measure,Meter 以及 Bang。基本配置倒是相当好处理,就是刷新频率、背景配置之类的信息。Measure 就是对某个信息的测量,比如时间、硬盘空间、CPU使用率、内存使用量等等,不过它还提供了一个“Calc”测量模式,就是计算一个公式,公式中可以将其他 Measure 作为变量,这是一个实现难点。Meter 就是对界面的定制,比如说绘制图片、直方图、曲线图、饼图等等,这个因为参数和种类都很多,因此做起来也比价麻烦。Bang 其实就是一些命令,因为以!开头所以叫这个名字。Bang 和 Measure 可以联系起来,比如说当测量数值达到某个值时执行某项命令;也可以和 Meter 联系起来,比如说点击某个图片执行某项命令之类。这个 Bang 的实现估计也够麻烦的。

今天写了一个晚上,因为对 PyGTK不熟悉,感觉写起来不是很顺利。代码发布到了 Github 上这个地方,现在还在开发中。现在倒是能够实现对部分 Meter 的绘制了,还支持了 Meter 的相对定位功能,效果看起来还行。明天继续来写吧~

贴几个图片,由于只实现了 Meter 部分,所以还不是正常工作状态,现在只是有了正确的 layout:

Thursday, April 30, 2009

pygtk 中的 gobject.timeout_add 函数

pygtk 中 gobject.timeout_add 的定义是
def gobject.timeout_add(interval, callback, ...)
这个函数被用于设置一个定时器,以便在固定的时间间隔 interval (单位:毫秒)后调用 callback 函数,之后的参数(...部分)则被传送给 callback 函数。callback 函数需要返回一个 bool 值,如果为 True 的话,则说明该定时器需要继续运行;而如果值为 False 的话,该计时器就会停止工作,不再定时调用 callback 函数。

callback 函数执行需要花费一定时间,因此可能会影响到定时器的准确性。按照官方文档给出的信息:
Note that timeout functions may be delayed, due to the processing of other event sources. Thus they should not be relied on for precise timing. After each call to the timeout function, the time of the next timeout is recalculated based on the current time and the given interval (it does not try to 'catch up' time lost in delays).

我对此不是十分清楚,于是 Google 了一些资料,做了点总结。一个比较能说明问题的例子:

假设 callback 函数执行时间为 1 秒,interval 的设置为 3 秒。那么当注册了定时器之后的第 3 秒结束时,也就是第一个 interval 的结尾,callback 函数被调用,在第 4 秒末执行完成,并返回 True。定时器函数获取 True 之后,知道需要继续执行定时调用,这个时候它会重行调整下次的调用时间,将下一次调用 callback 的时间定为 2 秒后。这是因为 callback 已经执行了 1 秒钟时间,而这 1 秒钟是算在 interval 之内的。所以,并不需要担心 callback 本身的执行带来的计时误差。

但是设想这样的一个情况,callback 的执行时间比较的长。比如 interval 设置为 3 秒,但是 callback 的执行时间是 4 秒。于是在第 3 秒的时候,原本该再次执行 callback 函数,可是由于 之前调用的 callback 还没有返回,于是这个执行计划被跳过,正如上面引用文档的结尾括号里的内容:“it does not try to 'catch up' time lost in delays”。

总结一下,以注册 timeout_add 函数的时间为原点,那么 timeout_add 函数总在最近的一个没有被 callback 函数覆盖的 interval 间隔点进行定时调用。

网络传输层的几个重要协议

最近对 RPC 有点兴趣,于是上 wikipedia 查了点资料,感觉挺有收获的。呵呵,以前网络原理没有好好学,现在补习一下。

传输层重要的几个协议是:
  • TCP: Transmission Control Protocol
  • UDP: User Datagram Protocol
  • SCTP: Stream Control Transmission Protocol
  • DCCP: Datagram Congestion Control Protocol
上网络课程的时候,我记得主要就讲了一下 TCP,而 UDP 只是稍稍做了介绍,SCTP 和 DCCP 则好像没有提到过。稍微比较一下几个协议的特点吧。

TCP 算是最常用的传输协议了,HTTP 和 FTP 都是基于它的。这个协议的特点是集成了拥塞控制,提供了丢包检测及重传、重复报文检测,保证发出去的数据有序到达接收方。可以说,这个协议对于使用者而言是最为“傻瓜”的,连接只有“成功”和“断开”两种状态。不过 TCP 由于在建立连接的时候要互相发送3个报文进行握手,之后才开始传输用户数据,所以会带来一定的额外开销。对于 HTTP 以及 FTP 协议而言,由于用户数据量比较大,所以对于这部分开销并不关心,此外 TCP 提供的拥塞控制也很有帮助。但是对于 RPC 这样的小数据量传输,TCP的开销就显得比较大了。另外对于一些实时性要求比较高的应用,比如网络游戏、网络电视、网络电话等,TCP 提供的丢包重传并不是十分有意义,因为丢了的包并不重要,而新的包才是更需要发送到接收方的。

UDP 则是一个很简单的传输协议,它几乎什么控制都不提供。它不保证发出的包能到达接收方,不保证报文到达接收方的顺序有序,而且同一个报文接收方可能会接收到多次,这套协议还不关心拥塞控制。TCP 协议提供的高级控制功能,UDP 都没有考虑。UDP 协议期望用户自己在应用中提供控制,或者用户不关心这些控制措施。虽然 UDP 看起来比较简陋,但是对于 RPC 和实时性要求高的应用而言,是最为高效的传输协议。此外,UDP 还能够直接支持多播和组播(这部分知识我现在还不是太清楚)。

UDP 的一个问题在于没有拥塞控制,这在安全上有一定的缺陷,于是 DCCP 被提出来解决这个问题。DCCP 在 RFC 4340 中提出,目前处于 proposed standard 状态。这个协议免去了在应用层实现拥塞控制的工作,并且已经在 Linux 2.6.14 内核中得到了支持。按照 wikipedia 给出的信息,这个协议类似于 TCP,但是却和 UDP 一样不对数据报文的重传、有序到达、唯一到达进行保证。个人感觉这套协议可能还是会有一定的建立连接时的开销,类似 TCP 建立连接时的握手过程。如果真是这样的话,这套协议还是不太适合 RPC,但是对于网络电视、网络电话这样的应用应该是很好的,因为这些应用的建立和用户数据传输的过程相比可以忽略。

SCTP 同样也是集成了 UDP 和 TCP 的特点,而且貌似更早于 DCCP ?它是在2000年就被提出来的。它的实现方式是将用户数据看做是消息,把它们拆分成小块进行发送。它可以看作是 Transaction-Oriented,接收方拿到的数据包和发送方发送的数据包是一样的(TCP会将发送的数据自动拆分到小包中),这一点类似于 UDP 的“确定边界”特性。

啊,困死了,回去睡觉吧。最后把 wikipedia 上的一个图表摘过来吧:

Feature Name UDP TCP SCTP DCCP
Connection oriented No Yes Yes Yes
Reliable transport No Yes Yes No
Unreliable transport Yes No Yes Yes
Preserve message boundary Yes No Yes Yes
Ordered delivery No Yes Yes No
Unordered delivery Yes No Yes Yes
Data checksum Yes Yes Yes Unsure
Checksum size (bits) 16 16 32 Unsure
Path MTU No Yes Yes Yes
Congestion control No Yes Yes Yes
Multiple streams No No Yes No
Multi-homing support No No Yes Unsure
Bundling / Nagle No Yes Yes No

from Wikipedia, original page to be found at here

Wednesday, April 29, 2009

Ubuntu 9.04 下,Apache 在同一 IP 下添加多个站点

最近忽然想在同一台电脑上用 Apache 建立多个站点,于是今天稍微研究了一下。Apache的默认端口是 80,我需要添加一个站点,使用的是 2080 端口。

首先到 /var 目录下添加一个新的文件夹 www2 (原来有一个 www 文件夹,已经被老站点使用了,所以新建一个),这个目录就将保存新站点的文件。

然后到 /etc/apache2 文件夹下,打开 ports.conf,可以看到原来已经有了一些信息。模仿已经有的配置,添加如下的两行:

NameVirtualHost: *:2080
Listen 2080

意思就是添加一个 2080 端口的站点,并且监听发送到这个端口的请求。

接下来,到 /etc/apache2/sites-available 目录下,可以看到已经有两个文件 "default" "default-ssl",它们是默认的站点配置以及添加了 ssl 安全保护的配置。复制 default 配置,比如:

sudo cp default web2

然后打开 web2 文件,将第一行从 "VirtualHost *:80" 改为 "VirtualHist *:2080" (2080是新站点的端口号),然后再找到 DocumentRoot 这一行,将后面的地址从 "/var/www" 改为 "/var/www2"。

接下来,需要在 sites-enabled 目录下添加一个指向 web2 文件的软链接:

(sites-enabled目录下)

sudo ln ../sites-available/web2 web2 -s

然后重新启动 Apache2:

sudo /etc/init.d/apache2 restart

现在就可以访问 2080 端口的新站点了。

Tuesday, April 28, 2009

Ubuntu 9.04 使用微软雅黑美化字体

关于 Ubuntu 的字体美化,已近有很多介绍了,但是我今天才实践了一次,对此做点记录吧。我参考的是这篇文章介绍的方法,不过可能因为版本不同的原因,有不少的区别。

首先从 Windows Vista 的字体目录 (C:\Windows\Fonts) 中找到雅黑的字体文件,并拷贝到 Ubuntu 的字体目录:

sudo cp msyhbd.ttf msyh.ttf /usr/share/fonts/truetype

将这2个文件的属性改成755

sudo chmod 755 /usr/share/fonts/truetype/msyh*.ttf

执行如下命令,刷新中文字体

sudo fontconfig-voodoo -f -s zh_CN

修改字体-语言配置:

sudo gedit /etc/fonts/conf.d/69-language-selector-zh-cn.conf

在所有的 Bitstream Vera Sans Mono 后添加 Microsoft YaHei

刷新字体缓存:

sudo fc-cache -f -v

打开 System-Preference-Appearance,在 Fonts 选项卡里可以设置字体为 Microsoft YaHei 了。

Sunday, April 26, 2009

Makefile 指定 gcc 文件输出路径

最近因为常常在 Linux 下写程序的原因,时常用到 Makefile ,以便于方便 C/C++ 程序的开发。不得不感叹 make 这个工具实在是好用,减轻了大量的工作负担。

最近才知道 Makefile 中存在“潜规则”,也就是默认的预定义依赖关系,比如 .o 文件是默认依赖于同名的 .c 文件的,并且 make 会自动执行这个依赖关系的命令本体,也就是说会自动将 .c 文件编译为 .c 文件。因此,如果你需要写一个 Makefile 将 prog.c 编译为 prog 的话,可以这样写:

all : prog

prog : prog.o
gcc prog.o -o prog

在这个 Makefile 里就没有写 prog.o 对 prog.c 的依赖。

然而这样有一个问题,就是生成的 .o 文件以及可执行文件都和源代码在同一个目录下,整个目录结构比较乱。我就希望能把生成的 .o 文件放置到一个 obj 目录下,然后可执行文件放到 bin 目录下。但要实现这个目标的话,岂不是要一个个文件改编译命令?如果工程量较大,上百个文件写起来会累死人的!

好在今天看到一个解决的方法,是通过修改“潜规则”来实现的。就用我现在的工程说明把。我的源程序都放在一个目录下(没有子目录),我希望把 .o 和可执行程序分别放到 obj 和 bin目录里。那么 Makefile 就这样写:

CC = gcc 编译器名
CFLAGS = -MD -Wall -O3 编译选项
LIBS = -lpthread 附加的库
OBJDIR = obj .o 输出目录
BINDIR = bin 可执行程序输出目录

.PRECIOUS: $(OBJDIR)/%.o 阻止 make 删除中间文件(不然以后还要编译)
默认目标
all: mkdirs $(BINDIR)/rpctest $(BINDIR)/headquarters \
$(BINDIR)/node_manager $(BINDIR)/extent_server

建立子文件夹
mkdirs : $(BINDIR) $(OBJDIR)

“潜规则”,OBJDIR 下的 .o 文件依赖于当前目录的同名 .c 文件
$(OBJDIR)/%.o : %.c
$(CC) -c $(CFLAGS) $(GCC_WALL_FLAG) $< -o $@

“潜规则",BINDIR 下的可执行程序依赖于 OBJDIR 下的同名 .o 文件
$(BINDIR)/% : $(OBJDIR)/%.o
$(CC) $(CFLAGS) $(GCC_WALL_FALG) $(LIBS) $< -o $@

建立文件夹
$(OBJDIR):
mkdir -p $@

$(BINDIR):
mkdir -p $@
添加 gcc 生成的依赖关系(-MD的输出)
-include $(OBJDIR)/*.d

clean :
rm -rf $(BINDIR) $(OBJDIR)

Sunday, April 19, 2009

加速Ubuntu 9.04 alpha 6

装了Ubuntu 9.04 alpha 6很长一段时间了,感觉什么都好,除了桌面的速度不能忍之外。我用的是HP Presario 3000 tu的笔记本,集成的Intel 945显卡,估计是9.04 alpha6的显卡驱动比较shit。今天刚好在这里看到了一个解决的方案,试了一下确实效果很好。原来跑glxgears的FPS只有60左右,现在则提高到了900左右,飞跃啊。终于能把compiz的许多特效解禁了,呵呵。

不过一个新的问题出来了,不知道是不是使用了rc版本内核的原因,现在启动的进度条又再度消失了,并且不能用以前的那个方法解决。为了速度考虑,只能忍忍了,暂时告别那漂亮的启动进度条了。希望9.04正式版本出来的时候,能够解决intel显卡驱动的问题。

Friday, April 10, 2009

Git的简单使用

最近刚刚开始在Github.com上创建项目,学了一下基本的git命令。我发现git确实比svn用起来要爽很多,而且Github.com的用户界面做得也十分友好,真让人想把所有项目都转到Github.com上。

和git相关的比较好的资料有:

  1. Everyday GIT With 20 Commands Or So
  2. Git User's Manual (for version 1.5.3 or newer)
  3. gittutorial(7) Manual Page

第一篇讲得比较简洁实用,2和3则是较为全面的参考文献。

就说说我到现在为止常用的几个命令把:

首先,我们需要建立一个git的仓库。使用git init命令就可以以当前目录作为基础建立一个git仓库。然后我们就可以开始添加代码文件了,不过在这之前可以先建立一个.gitignore文件,标记出哪些文件需要忽略。

.gitignore文件可以这样写:

#忽略所有的svn文件夹,注意最后的/说明了忽略的是一个目录而不是一个文件
.svn/

# 忽略所有的sqlite3数据库
*.sqlite3

在配置完毕.gitignore文件之后,就可以开始加入代码了:

git add .

然后可以在修改完毕之后可以commit:

git commit -a

接下来添加一个远程的仓库,并取名为origin:

git remote add origin XXXXX

然后将修改的代码发布到远程仓库中,这里master为本地的代码主线:

git push origin master

有需要的时候可以随时产生一个分支:

git branch new-branch

使用git branch命令可以显示本地的分支,带*号的是当前工作分支。如果要显示远端的分支,可以用:git branch -r显示。

如果要添加远程代码仓库中的一个分支,比如说叫做maint的分支:

git branch maint origin/maint

这样maint分支就在本地被添加上了。

如果要切换工作分支,使用git checkout:

git checkout master
git checkout new-branch

需要更新代码的时候:

git pull

相当于svn update。

现在我就使用了以上的一些git功能,其他的例如git fetch还没有实际使用过,并不是很明白怎么使用。总体感觉git好强大呀,现在都想把以前的代码都从svn转换到git下来了:D

Wednesday, April 8, 2009

Ubuntu如何添加新的用户并加入到sudoer中

添加一个名为nova的用户:

(root 权限运行)

adduser nova

(输入密码等配置)

(root 权限运行)

visudo -f /etc/sudoers

在其中加入一行(模仿root):

nova ALL=(ALL) ALL

Linux下的Zombie进程

在Linux下,可以调用fork()函数创建新的进程。父进进程的一个责任就是当子进程结束之后,调用wait4()系统函数对其进行回收。如果在父进程没有及时处理(比如,在运行一个很耗费时间的循环),那么子进程由于没有被及时回收,就被标记为Zombie进程。

为了避免Zombie进程的出现,有以下方法可以解决:

1 两次fork()
首先说一下,如果父进程在子进程结束前就运行完了,那么Linux会自动地将子进程的父亲修改为init进程,这样就由init进程来负责对子进程的回收工作。于是,可以用下面的代码来防止Zombie进程的出现:

pid = fork(); // 第一次fork
if (pid == 0) { // 子进程
  pid = fork(); // 第二次fork
  if (pid == 0) {
    // 子进程代码
  } else { // 中间生成的父进程,立即退出
    exit(0);
  }
} else {
  // 父进程代码
}

以上代码通过两次fork,一共产生了3个进程,第二次fork时的父进程通过exit()直接退出了,这就使得最终的子进程被移交给inti线程进行回收工作,于是避免了Zombie进程的出现。

2 忽略SIGCHLD信号
当子进程结束的时候,系统会向父进程发出一个SIGCHLD信号,通知子进程的完结。如果我们显示地忽略这个信号,那么子进程就不再需要等待父进程的回收。可以通过如下代码实现:

signal(SIGCHLD, SIG_IGN); // 显示忽略信号
// 之后开始fork操作
pid = fork();

3 使用waitpid等待子进程结束
这个就很显然了,保证了子进程在父进程之前结束,于是也就避免了Zombie进程的出现。

Wednesday, April 1, 2009

知道Rails中的routes.rb怎么使用了

Rails利用routes.rb中的配置来将一个http请求映射到相应的controller的action中。在config目录下的routes.rb文件中有大量的注释,有助于理解映射的原理。

首先要注意到 :controller 和 :action 是关键的参数,它们俩决定了调用的controller以及相应的action,所以必须要给出这两个参数的值。那么怎么给出它们的值呢?有两个方法:

1 在map的地址模板中给出

最标准的实例就是 map.connect ':controller/:action' 了,这就是说把http request中的两个部分截取下来,作为controller和action名字。比如 localhost:3000/user/show_all 就是对应了User这个Controller的show_all方法。

我们还可以加入其他的信息,比如 map.connect ':controller/:action/:id',这就是说把http request中的第三部分截取下来,作为一个名为“id”的参数,传递给调用的方法。在ruby代码中,可以用param[:id]获取到这个参数的值。

如果 :id 参数包含一些特殊字符,例如‘.’(period)的时候,默认的映射就会失败。这就需要稍微增加一些辅助信息给ruby了。我对于这些带冒号开头的URL片段的理解是,它们就是一些正则表达式,而默认的正则表达式不能很好的识别诸如period这样的字符,于是需要自己重新设定一下正则表达式:

map.connect ':controller/:action/:id', :id=> /[a-zA-Z0-9._@]+/

这样以来,如下的http请求也能被很好的处理了:

localhost:3000/user/add/someone@some.com

2 直接指定Controller以及Action

routes.rb中的注释代码很好的给出了范例:

map.connect 'products/:id', :controller=>'catalog', :action => 'view'

当用户给出一个http请求到 products/some_product 的时候,ruby on rails会调用 Catalog的view方法来进行处理,而 param[:id] 则包含了 "some_product" 这个信息。

Tuesday, March 31, 2009

修正Ubuntu开机启动进度条消失的问题

今天试着把Ubuntu升级到了9.04,感觉还不错,不过似乎显卡驱动有一点点问题,感觉图形界面比较的卡,不知道正式版本会不会有所优化。

9.04的开机画面比较好看,有一个很漂亮的进度条,似乎是学习Mac的。比较令我不爽的是之前不知道做了什么操作,开机的时候进度条会消失,转化为文本界面,输出一些类似于“Loading files needed to boot”之类的信息,很是难看。今天终于在官网上找到了一个bug track解决了这个问题:


按照上面的说法,我在某一次使用了Ghost 4 Linux恢复系统之后,SWAP分区的UUID被修改了,于是Ubuntu的文件系统出现了错误。改正这个方法的步骤如下:

1 确保安装了最新版本的initramfs-tools
2 运行sudo blkid,记录下SWAP的UUID
(注:如果SWAP分区没有UUID,那么可以用gparted重新格式化SWAP分区,新产生的分区就会有UUID了)
3 确保/etc/fstab中的SWAP分区的UUID与第2步中的UUID相同
4 确保/etc/initramfs-tools/conf.d/resume中的SWAP UUID与第2步中的相同
5 运行sudo update-initramfs -u
6 重启

于是一切OK

Wednesday, March 25, 2009

终于知道怎么用ThuThesis了!

要开始准备一下本科毕设论文了,于是把学校的模板ThuThessi 4.4下载了下来。编译过后就可以获得pdf文件,不过问题是这些pdf里的中文无法复制出来(乱码)。上网搜了一下午资料,试过了不知多少种配置,都不能行。最后无意间发现了一个最简单的做法:

latex thuthesis.ins 生成配置文件
pdflatex main.tex 编译main.tex,论文主体(第一遍)
gbk2uni main 编码转换,如果不做这一步的话,书签会是乱码
pdflatex main.tex 再次编译main.tex,生成最终的论文主体

这样生成的论文就可以复制出正确的中文来了。

此外,附加说一下,怎样在Ubuntu下编写带有中文的tex文件。
安装好texlive以及latex-cjk-chinese之后其实就有很好的中文支持了,测试文件:

\documentclass{article}
\usepackage{CJK}
\begin{document}
\begin{CJK*}{UTF8}{gbsn}
\title{中文}
\maketitle
啦啦啦
\end{CJK*}
\end{document}

在Linux下还可以使用dvipdf, dvipdfm, dvipdfmx等命令将dvi文件转化为pdf文件。

Tuesday, March 24, 2009

NFS文件系统的配置






NFS文件系统的配置

系统环境

Server以及Client都是Ubuntu系统

相关命令

nfs(5), exports(5), mount(8), fstab(5), nfsd(8), lockd(8), statd(8),rquotad(8), and mountd(8)

Server 端安装与配置

首先,在 Server 上安装 nfs-kernel-server 。然后编辑 /etc/exports 文件,例如希望共享 /home/nova/store 目录给 ip 为 10.0.*.* 的用户,则加入:

/home/nova/store    10.0.0.0/255.255.0.0(rw,sync,no_subtree_check)

其中,255.255.0.0 是掩码,rw 代表用户可以进行读写。

编辑完毕之后键入命令

sudo exportfs -ra

刷新文件系统。之后可以用 exportfs 命令检查是否成功的配置好了文件系统,如果看到

/home/nova/store
                        10.0.0.0/255.255.0.0

则说明以及成功。

Client 端使用方法

Client 端需要安装 nfs-common 。然后建立一个新目录(比如 shared)以便加载NFS文件系统:

sudo mount 10.0.2.3:/home/nova/store shared

这里,10.0.2.3是Server端的ip地址。加载完成之后就可以使用了。

Friday, October 24, 2008

虚拟机调研报告






Virtual Box:



Virtual Box 的速度比较快,并且支持大量的操作系统,也有现成的API文档,支持COM方式和webservice两种方式调用。其优势在于桌面应用。网络方面,为了使得Guest OS可以被外界用户所访问到,需要建立网桥,过程并不是很麻烦。我们在Windows操作系统下建立了3个不同的Guest OS并且对其网络进行测试,结果令人满意。在虚拟机启动的时候,Windows会通过网桥机制为各个虚拟机的网卡动态地设置ip地址。



总的来说,我们认为Virtual Box有如下一些优势:



  1. 速度快,并且不需要硬件的支持


  2. 有现成的API,并且提供COM以及webservice的方式进行调用。





但是,Virtual Box有如下一些劣势:



  1. 不支持动态迁移,并且官方并没有给出开发的意向


  2. Ubuntu Server Edition不能安装Virtual Box (需要进一步确认)




TODO:Ubuntu下测试Virtual Box (KVM和Virtual Box有冲突,已经装了KVM的内核下,Virtual Box 1.6 启动不了,也许 2.0版本可以运行)





XEN:

XEN同时支持全虚拟化(需要硬件支持)以及半虚拟化,并且支持动态迁移。XEN已经开发有3年以上,算是比较成熟的一个虚拟机。但是自从Ubuntu 8.10开始起,将不再具有对XEN的支持,因此在Ubuntu平台上XEN的后续开发不是很现实。

TO BE CONTINUED....



KVM:




KVM是比较新的一个虚拟机,而且在短时间内就得到了Linux内核的支持。自从2.6.20开始的linux内核都添加了对KVM的支持,这是KVM的一大优势。KVM的安装很方便,而且虚拟机的创建比较简单,已经有一个现成的Python脚本可以直接从命令行创建虚拟机,并且可以作许多的设置。该脚本的说明中,甚至给出了直接从命令行创建虚拟机、对镜像分区、配置网络、设置用户密码并且安装相应软件的详细方法。不过这些功能似乎只适用于Ubuntu Host OS,Windows Host并没有给出具体的说明。在官方说明中指出KVM在安装Windows XP时,在电源管理部分有一个小问题,但是并不影响系统的使用(在我们的测试中,WinXp在从光盘拷贝完文件到硬盘上之后,在一次重启之后直接就挂掉了) 经过我们的测试,发现Winxp是可以安装的:

kvm-img create -f qcow2 win.cow 5G    建立cow格式的硬盘,大小为5G


kvm -hda win.cow -boot d -m 192 -localtime -net nic -net user -soundhw es1370 -cdrom XPSP2VOLIBM_EN.iso       配置硬盘、时间、网络以及声卡,从光盘开始起动安装winxp


kvm -hda win.cow -boot c -m 192 -localtime -net nic -net user -soundhw es1370         安装完后,从硬盘启动winxp

安装速度很快,并且没有任何问题

Vista的安装我们目前还未测试(TODO)。Windows 2003 Server可以安装。Windows 2000及以前版本的安装并不支持。

我们利用KVM安装了Ubuntu 8.04 desktop和server 版本,在硬件的支持下,速度和真实电脑没有太大区别,表现超过了Virtual Box。但是我们在笔记本电脑上测试时,由于没有硬件的支持,仅能利用qemu进行模拟,速度不到物理机器的1/4。

我们看了一下几个Linux社区上关于KVM和XEN的评论,基本都认为KVM是未来虚拟机的方向,比XEN要有前景一些。KVM有以下的一些情况:



  1. KVM直接得到来自Linux内核的支持,因此可以做得小巧一些
  2. KVM目前还未支持动态迁移,但是该方面的工作已经开始,相信很快就会有支持动态迁移的版本


Friday, May 9, 2008

Tomoyo ~ Lovely girl!


This is Tomoyo from Anime CLANNAD.
Posted by Picasa