Sunday, July 01, 2007

用 aptitude 处理 debian 软件包的依赖关系

(内容并不超出 aptitude 文档的范围,这里用以提示给没有阅读完整文档的用户)

在使用 aptitude 安装、删除、升级软件包的时候,有时会遇到依赖关系问题,通常可以利用 aptitude 的自动解决功能,但有的时候,我们希望能手工选择一下如何处理依赖关系。

当在软件包界面进行选择时,在出现依赖关系问题时,会在界面下方得到红色提示,这时,按 e ,会得到依赖关系解决方案界面,里面列出了一个解决方案,包含安装、升级、降级、保持、删除若干个软件包,上下移动光标,会发现下方的区域会列出每个软件包可以用来解决该问题的几种方案。

这时可以用 ``.'' 和 ``,'' 前后翻阅不同的解决方案,翻到哪,再按 g 就会执行哪个方案了。

当然,我们还可以更精确的选择,解决方案界面,对哪个软件包按 a 就表示接受对这个软件包的这种处理方式,这样,就极大地限制了备选方案的数量,同理,对软件包按 r 就可以拒绝一个软件包的处理方式。结合 a/r/./, 可以更快地找到合适的解决方案。
fdupes: 发现文件的重复拷贝

在使用了一段时间的计算机之后,很多文件都可能被保存或复制了很多份,而且常常是在无意状态下造成这些副本的,你是不是想把他们找出来并删掉呢?

原则上讲,这个工作并不难,但是比较复杂,需要列出所有文件,比较大小乃至 md5,因为同名文件不一定有相同的内容,尤其是对于 README 这样的文件名,而且相同的文件不一定名称也一样。

fdupes 就是这样一个有用的小工具,它能很高效率地完成这一工作,用法很简单: 在 fdupes 后面加上要查看的所有目录,同时,还有一些开关:
  • -n 不比较所有大小为0的文件
  • -r 递归搜索所有子目录
其它功能参考 man page 吧 :)

Sunday, June 17, 2007

[近期译文] GIT 简要教程

git 简要教程 (适用于 1.5.1 或更新版本)

原文链接: http://www.kernel.org/pub/software/scm/git/docs/tutorial.html


这个教程将介绍如何将一个新的项目导入到 git 之中,如何修改项目并如何将这些变更与其他开发者分享。

如果你更感兴趣如何用 git 取出一个项目,比如,测试软件的最新版本,你可能更应该看看 The Git User's Manual 的前两章。

首先,记住你可以用 man 来获取 git 的文档,比如 "git diff" 的文档可以用如下命令察看:

$ man git-diff

在做任何改动之前,最好把自己的名字和 email 地址介绍给大家,最简单的方法就是:

$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com

导入一个新项目

假设你有一个名为 project.tar.gz 的 tarball 作为项目的初始内容。你可以如下操作来把它至于 git 版本控制之下。

$ tar xzf project.tar.gz
$ cd project
$ git init

Git 将会如下回复:

Initialized empty Git repository in .git/

现在,你已经初始化了工作目录——你可能已经注意到了名为 ".git" 的一个新目录了。下一步就是使用 git-add(1) 命令告诉 git 当前目录的所有文件全是项目的一个快照:

$ git add .

这个快照目前存放在一个临时区域之中,在 git 中称为 "index"。使用 git-commit 命令,你可以把 index 的所有内容永久性地存放到软件仓库之中:

$ git commit

这条命令会向你提示输入版本变更信息。这样,你的项目的第一个版本就已经存入 git 之中了。

进行修改

修改一些文件之后,你可以将

更新这些内容到 index 之中:

$ git add file1 file2 file3

现在,你已经准备就绪,可以提交了。现在你可以使用 git-diff(1) 命令的 --cache 参数

来查看都有哪些内容将会被提交:

$ git diff --cached

(如果不使用 --cached 参数,git-diff(1) 会显示所有还没添加进 index 的已经做出的改动。) 你也可以使用 git-status (1) 来获得一些当前状况的概要信息:

$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1
# modified: file2
# modified: file3
#

如果你需要进行更多改动,现在就可以进行,然后可以添加到 index 之中。最后,使用如下命令提交改动:

$ git commit

这将再次要求你输入关于这次改动内容的描述性信息,之后记录下

的项目新版本。此外,如果想省掉提交之前的 git add 命令,你可以直接用

$ git commit -a

这样会自动检测所有修改过的文件 (不包括新文件) ,并一气呵成地将它们添到 index 之中,并提交。

关于提交的描述信息: 虽然这个信息不是必须的,但提交信息描述最好以一行不超过50个字符的概要性信息来开头,在一个空行之后再进行更多的描述。比如那些将 commit 转化为 email 的工具就会把这个第一行作为邮件标题,其余的提交内容则放在邮件内部。

Git 跟踪内容而不是文件

很多版本控制系统提供了一个 "add" 命令用来记录一个新文件。而 git 的 "add" 命令更加简单也更加强大: git-add 既用于新文件也用于新近改动的文件,在所有这些情况下,它在 index 中对所有的文件与状态进行一次快照,这样就可以在下一次 commit 命令中进行提交。

查看项目历史

在任何时候,你都可以如下查看所有你进行过的改动

$ git log

你可能还想看到每一步改进中的所有完整的 diff ,这可以使用如下命令

$ git log -p

浏览改动的概要对于获得每一步修改的情况常常是比较有用的,可以使用如下命令

$ git log --stat --summary

管理分支

一个 git 仓库可以包含多个开发分支。使用如下命令可以建立一个称为 "experimental" 的新分支

$ git branch experimental

如果你运行命令

$ git branch

你将可以得到类似下面的已有分支的列表

  experimental
* master

"experimental" 就是你刚刚建立的那个分支,而 "master" 分支则是建立仓库的时候自动创建的缺省分支,里面的星号表示你当前所在的分支;输入命令

$ git checkout experimental

就可以切换到 experimental 分支。现在修改一个文件,并提交改变,然后重新回到 master 分支:

(edit file)
$ git commit -a
$ git checkout master

你会发现,刚才的变更已经不可见了,这是因为这个改变是发生于 experimental 分支的,而你现在已经回到 master 分支了。

(edit file)
$ git commit -a

这里,两个分支已经产生不同了,每个分支上都发生了不同的改动。要把 experimental 中的改变也合并到 master 之中,运行命令

$ git merge experimental

如果两者的改变并不冲突,那么就算是完成了。而如果这里有冲突,有问题的文件左边会显示出标记,以表明这个文件发生了冲突;

$ git diff

上述命令将会列出具体的冲突。一旦你编辑文件解决了冲突,

$ git commit -a

这个命令将把合并的结果提交。最终,

$ gitk

会显示出漂亮的图标以展示历史变革。



这里你可以使用如下命令删除 experimental 分支。

$ git branch -d experimental

这个命令会确定 experimental 中的所有改动已经在当前分支当中了。


如果你在 crazy-idea 分支中进行开发,然后又后悔了,你可以用如下命令删除分支
$ git branch -D crazy-idea

分支操作十分简单而且代价低廉,所以适合于尝试一些东西。

使用 git 进行协作

假设 Alice 在 /home/alice/project 中的 git 仓库启动了一个新项目,而在本机中也拥有 home 目录的 Bob 想要贡献一些代码。


他可以以如下工作开始:

$ git clone /home/alice/project myrepo

这会新建一个名为 "myrepo" 的目录,里面包含了 Alice 的仓库的一份克隆。这份克隆与原始项目完全一致,可以处理自己的一份原始项目历史。


之后,Bob 进行了一些变更并提交了这些变动:

(edit files)
$ git commit -a
(repeat as necessary)

当他完成的时候,他告诉 Alice 将 /home/bob/myrepo 之中的变动导入到原始仓库之中。她使用如下命令来完成这一工作:

$ cd /home/alice/project
$ git pull /home/bob/myrepo master

这回合并 Bob 的 "master" 分支到 Alice 的当前分支。如果 Alice 也已经修改了某些内容,她需要手工修复冲突。(注意,"master" 参数实际上并不是必要的,因为这是缺省分支。) "pull" 命令包括两个操作: 从远端分支中取出改动,然后合并到当前分支之中。


当你只在一个很小的小组里工作的时候,通常不会频繁地访问同一个仓库。通过定义仓库的快捷方式,可以让访问远程仓库更方便一些:

$ git remote add bob /home/bob/myrepo

这样,你可以如下用 "git fetch" 命令仅取出改动,而不把它们合并到当前分支之中:

$ git fetch bob

和长格式不同,当 Alice 使用 git remote 设置的快捷方式从 Bob 的仓库中获取内容的时候,取出的内容存储在一个 remote tracking 分支之中,在本例中是 bob/master。所以,如下操作

$ git log -p master..bob/master

将会列出从 Bob 从 Alice 的主分支中分支出去以后的所有改动。

$ git merge bob/master

这个合并也可以通过从自己的 remote tracking 分支中 pull 来做到,如

$ git pull . remotes/bob/master

注意,git pull 总是合并进当前的分支,不论命令行给出的是什么。


之后,Bob 可以如下使用 Alice 的最近改动更新自己的仓库

$ git pull

这里,他不需要给出 Alice 的仓库的位置;当 Bob 克隆了 Alice 的仓库的时候,git 在仓库设置中保存了她的仓库的位置,即 pull 所使用的位置:

$ git config --get remote.origin.url
/home/bob/myrepo

(git-clone 创建的完整配置信息可以用 "git config -l" 获得,git-config(1) 的 man page 解释了所有选项的含义。)


Git 也在 "origin/master" 分支保存了一份 Alice 的主分支的原始拷贝:

$ git branch -r
origin/master

如果其后 Bob 决定转到另一台主机上工作,他还可以通过 ssh 来克隆原始仓库:

$ git clone alice.org:/home/alice/project myrepo

此外,git 本身也有远程协议,并且可以使用 rsync 或 http,详细情况可以查看 git-pull(1) 的 man page。


Git 也可以使用类似 CVS 的工作方式,使用一个中心仓库,所有用户将改动推送到仓库之中,相关内容可以查阅 git-push(1) 的手册页或 git for CVS users

浏览历史

Git 的历史是通过一系列相互关联的 commit 构成的。我们已经通过 git log 命令看到了这些提交的列表。注意,每个 git log 条目的第一行是那次提交的名称:

$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <junkio@cox.net>
Date: Tue May 16 17:18:22 2006 -0700

merge-base: Clarify the comments on post processing.

把这个名称用于 git show 命令,可以得到提交的详情。

$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7

不过还有其他办法来指代这次提交。你可以只使用名称的开始部分,只要它足够长,保证在所有提交中是惟一的就行了:

$ git show c82a22c39c   # the first few characters of the name are
# usually enough
$ git show HEAD # the tip of the current branch
$ git show experimental # the tip of the "experimental" branch

每一次提交通常都有一次提交作为 "parent" ,它是项目的前一个状态:

$ git show HEAD^  # to see the parent of HEAD
$ git show HEAD^^ # to see the grandparent of HEAD
$ git show HEAD~4 # to see the great-great grandparent of HEAD

Note that merge commits may have more than one parent:

要注意,合并提交可能会有多个 "parent":

$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^)
$ git show HEAD^2 # show the second parent of HEAD

你还可以给你的提交一个名字; 命令

$ git-tag v2.5 1b2e1d63ff

让你可以使用 "v2.5" 来指代 1b2e1d63ff。如果你想把这个名字与他人共享 (比如标记一个发布版本),你应该建立一个 "tag" 对象,可能还需要签署它; 详情请查看 git-tag(1) 的 man page。


任何 git 命令都可以使用上述任何一种名字。比如:

$ git diff v2.5 HEAD     # compare the current HEAD to v2.5
$ git branch stable v2.5 # start a new branch named "stable" based
# at v2.5
$ git reset --hard HEAD^ # reset your current branch and working
# directory to its state at HEAD^

小心使用上述最后一个命令: 这将丢失工作目录中的所有改动,他还会清除本分支内随后的所有提交。如果这个分支是包含这些提交的惟一分支,它们将永远地丢失了。此外,不要对一个公众可见的、有其他开发者从中 pull 内容的分支使用 "git reset" 命令,这将导致一些不必要的合并来清除其他开发者的历史信息。如果你需要取消已经推送的改动,可以使用 git-revert(1) 命令。


git grep 可以在项目的所有版本历史中寻找字符串,而如下命令

$ git grep "hello" v2.5

会在版本 v2.5 中寻找所有 "hello" 的踪迹。


如果你不提供 commit 名称,git grep 会在你当前的目录中搜索所有由 git 管理的文件。于是,如下命令

$ git grep "hello"

是搜索 git 跟踪的所有文件的便捷的方式。


很多 git 命令可以处理一组提交,可以通过多种方式来指定版本。这里是一些 git log 的例子:

$ git log v2.5..v2.6            # commits between v2.5 and v2.6
$ git log v2.5.. # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile # commits since v2.5 which modify
# Makefile

你给出的范围的起始值不一定比终止值更老,比如,"stable-release" 分支可能会在 "master" 分支之后相当长一段时间才会引入同一个提交内容,这样

$ git log stable..experimental

将会列出 expermental 分支之中已经有的,而 stable 分支却还没有的提交,而命令

$ git log experimental..stable

将会列出 stable 中已有、但 experimental 却没有的提交。


"git log" 命令有一个弱点:必须将所有提交在一个列表中呈现出来。当项目历史中有多个不同开发分支并最终合并到一起时,"git log" 中呈现出来的顺序可能没什么意义。


大部分有大量开发者的项目 (比如 linux kernel 或 git 本身) 都经常合并分支,gitk 可以更好地将这些合并变化展示出来。比如,

$ gitk --since="2 weeks ago" drivers/

这个命令允许你浏览过去两个星期中在 "drivers" 目录之中的任意提交。(注意: 你可以按住 ctrl 键然后用 "-" 和 "+" 来调整 gitk 的字体大小。)


最后,大部分命令可以带有文件名,这可以用于指定某次提交中的某个文件,从而指定某个文件的某个版本:

$ git diff v2.5:Makefile HEAD:Makefile.in

你还可以用 "git show" 命令去查看任意文件的任意版本:

$ git show v2.5:Makefile

下一步学习

这个教程应该足够你的项目进行基本的项目发布版本管理。不过,要完全深入地理解 git 的强大功能可能还需要理解两个简单的概念:

  • 对象数据库是个相当阳春的系统,用于存储你的项目的历史,包括文件、目录以及各次提交。
  • 索引文件是目录树的状态的缓存,用于建立提交、取出工作目录并保存一次合并中包含的不同的目录树。

本教程的第二部分 解释了对象数据库、索引文件以及一些其他你在使用 git 中所需要了解的零七八碎的概念。


如果你不想在这条路上继续下去,还有一些细枝末节的东西可能十分有趣:

  • git-format-patch(1), git-am(1): 用于将一系列 git 提交转化成 email 发送的补丁或反之,对于 linux 内核这样的高度依赖于邮件发送的补丁的项目来说十分有用。

  • git-bisect(1): 当你的项目发生倒退的时候,一个跟踪发现错误的方法就是通过历史发现那个罪魁祸首的提交。Git bisect 可以帮助你进行二分查找发现那个提交。它能在一个有很多分支合并的具有复杂非线性历史的项目中十分灵巧地进行接近最优的搜索。
  • Everyday GIT with 20 Commands Or So

  • git for CVS users.


原文最后更新于: 11-Jun-2007 01:21:27 UTC

Sunday, June 03, 2007

智力竞赛节目的致命伤

从北京电视台的"星星擂台","SK 状元榜", 到中央台的"三星智力快车", 中学生知识竞赛类的节目我断断续续地看了十多年了, 一直以来以博古通今自居的我(其实也都是半瓶子醋, 远没到通的地步), 总觉得答题中学生的水平比不上中学时代的我, 不过, 在我看来, 这些节目的致命伤不在学生的水平, 而在编导和主持人的水平.

遥想当年, 星星擂台主持人旭东的水平似乎还是不错的, 至少在我的水平之内没看出什么问题来, 不过另两个节目却难以恭维. 那年看"三星智力快车", 一个同学把"忽必烈"答成"成吉思汗"了, 主持人在判断正误之余, 卖弄了一回"知识", 居然告诉该同学, 两者是父子关系, 从此, 我再也不看这个节目了...... 通过这件事, 我有一个明确的认识, 主持人不知道就不应该多说

不过今天, 我发现, 主持人需要控制的不只是自己, 今天一边早点一边看"SK 状元榜", 一道题要从三个图片中区分出"歼-10" 战斗机, 一位回答正确的同学解释的时候漏洞百出, 称 Su-27 为 Su-35, 称 J-10 的鸭翼为前掠翼, 主持人居然还称赞他太专业了.......

真不知道这样录制的节目怎么最终还播出了...

Monday, May 28, 2007

翻了翻《战争论》

周末在家的时候睡觉之前翻了翻多年前购入的卡尔. 冯. 克劳塞维茨的《战争论》 ,感觉和《孙子兵法》比强很多阿,呵呵,对战争本身分析得很深入,典型的西方的分析方式的思维。

Friday, May 25, 2007

我的致谢

感谢赋予我生命的父母;
感谢赐予我生活的世界;
感谢赠予我帮助的朋友;
感谢给予我爱情的女友。
当人生失意的时候,你会明白什么是值得珍惜的,什么是不得不放弃的,什么是应该铭记的;而当人生得意的时候,你会学到的只有一个词—— “感谢”。

当我结束五年硕士与博士研究生生涯的时候,我必须要感谢我的师长们,不论是给我高屋建瓴的言传身教张平老师,还是约束、关心我们一言一行的刘宝玲老师,更有亦师亦友的纪阳老师、唐晓晟老师、李亦农老师、冯智勇老师,你们或激昂、或平易、或严谨、或理性的言行无时无刻不在引导我前进。我也会感谢无线新技术研究所给我这片成长的土壤、这个挥洒的舞台,我从这里获得了很多、赢得了很多,也留下了一份永久的美好印象。

我当然还要感谢曾经的师兄师姐们,张新的领导风范、柴慧娟的古道热肠、王黎敏的热忱执着都在影响着我,永远也不会忘记他们所给我的教诲。还有同一级的挚友们:小白、大黄、小毕、老战、阿呆、罗总、胡峥……永远怀念我们一同拼搏的日子。

还不能忘记给我快乐、给我支持的师弟师妹们,也祝福你们。

当这份论文完成的时候,我不能不感谢帮助我完成整篇论文的那些开源软件的作者和贡献者们,他们包括但不限于:
  • Linus Torvalds, FSF 和其他无数贡献者开发的GNU/Linux 操作系统,是我完成整个论文的基础平台;
  • D. Knuth 教授和Leslie Lamport 的杰出发明:TEX 和LATEX 这是我所使用的排版系统,论文完成后,作者为论文所开发的模板将会留下来供其他人使用,这个模板还参考并部分使用了清华的王磊设计的清华大学博士论文模板的内容;
  • Werner Lamberg 的CJK是论文中文排版的核心支持;
  • 张林波老师的CCT 中文TEX 排版支持中的很多工具都被用在论文档中了,还要感谢oseen的打包工作;
  • NS-2 的开发者和贡献者们,以John W. Eaton 为首的Octave 的开发者,还有Maxima 的开发者们,他们提供的工具分别是论文中进行离散事件仿真、数值分析和符号运算所使用的工具。
  • Thomas Williams, Colin Kelley 和其他很多贡献者开发的Gnuplot,所有曲线、直方图、三位曲面图的绘制都由Gnuplot 完成,而精美的状态图、示意图大多由John Hobby 开发的Metapost 完成,此外其他的图片制造工具还有Dia, LATEX msc宏包等。
  • Bram Moolenaar等开发的VIM是本论文所用的编辑器,还有它的扩展LATEXsuit
在表达谢意的同时,我骄傲地向您,也向其他阅读者宣布:本论文的撰写过程中所使用的工具全部为开源软件或其它合法取得的软件,不仅内容是原创性的,而且完成过程也是合法、尊重著作权的。(注:本文所用的字体分别为文鼎免费字体和付费购买的方正字体。)

最后,我更要感谢这位伴我度过三年博士生涯的女孩—— 王海娟,她即将成为我的新娘,三年之中我们一起走过,不论是一同徜徉于校园还是天各一方、远隔重洋,我们的心间总有剪不断的红线。患难见真情,当我受尽挫折、接近放弃的时候,是她的坚定和果敢感染了我,让我义无反顾地向前冲,去挑战自我的顽疾,去战胜人性的弱点,她不仅是我疼爱的对象,更是我一同战斗一生的坚定伙伴。

Saturday, May 05, 2007

忙里偷闲解决了一个笔记本温度传感器的问题

自从内核从 2.6.16 升级到 2.6.18 之后, 笔记本的温度传感器工作不很正常,无法检测到 I2C 总线上的传感器,确切地说是 SMBus 总线控制器无法正常工作 [1]

后经过检查,认定是 ACPI DSDT 中 SMBL 字段导致的问题 [2],PCI 总线分配的 SMBus IO 空间为 0xe800 - 0xe81f 共 32 字节,而 ACPI BIOS DSDT 表中却有
Name (SMBS, 0xE800)
Name (SMBL, 0x10)
的字段,即,SMBus IO 空间长度 16 字节,使用 Intel ASL 编译器 (IASL) [3] 修改 DSDT 中 SMBL 为 0x20 并使用此定制 DSDT 后,问题被解决。[2]

此 问题刚刚初现的原因是 [4] 中补丁进入 Linux 内核之前,驱动申请该该 IO 区域长度是固定为 16 字节的,无论 PCI 总线给予多大空间,这样尽管 DSDT 和 PCI 总线不一致,但没有暴露出冲突,不过,自从新的内核采用了更灵活的地址空间确定方式后,此问题被暴露出来 [5]。这对于一般 的 ACPI BIOS 来说,不是一个常见问题,所以没有其他人报告过。

我已经将自己修改过的对应华硕 M2Ne 笔记本(M2400Ne, Intel Dophin Pentium M CPU, 855GM/ICH4) 0204 版本 BIOS 的 DSDT 上传至 Linux ACPI 网站 [6]

[1] http://lists.lm-sensors.org/pipermail/i2c/2007-May/001118.html
[2] http://lists.lm-sensors.org/pipermail/i2c/2007-May/001129.html
[3] http://www.intel.com/technology/IAPC/acpi/downloads.htm
[4] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=6dcc19dfbc84b2ea5428711b7a47146b5b1788bb
[5] http://lists.lm-sensors.org/pipermail/i2c/2007-May/001134.html
[6] http://acpi.sourceforge.net/dsdt/view.php?id=787

Friday, March 16, 2007

[译文] 使用 Cscope 和 SilentBob 分析源代码

Title
Using Cscope and SilentBob to analyze source code
Date
2007.03.09 4:01
Author
StoneLion
Topic

http://programming.linux.com/article.pl?sid=07/03/05/1715201

当你开始研究一个不熟悉的项目的源代码的时候,对源代码的结构、函数和类的名称的含义等都不甚了解。这时,虽然我们可以使用 tags 来查看他们的定义,但是却很难通过一个一个看这些定义来得到全句的信息。Cscope 和 SilentBob 就是两个可以帮助我们分析不熟悉的源代码的工具。他们可以帮助你查找符号的定义,判断某个函数在哪里被调用了,发现某个给定的函数调用了哪些其他函数,以及在源代码中进行字符串模式匹配。使用这两个工具,你可以通过高速、有目的性的阅读代码来节省大量的时间,而不需要去手工 grep 所有代码文件。

使用 Cscope

Cscope 是一个非常流行的实用工具,大部分现代发行版都包含它。虽然 Cscope 最初被设计用来分析 C 代码,不过实际上,它在分析其他语言,诸如 C++ 和 Java 的时候同样好用。Cscope 拥有一个基于 ncurses 的界面,不过,它同样支持命令行模式,以便和其他前端程序一同工作,这些前端包含很多主流编辑器,如 Emacs 和 Vim。

当你调用 Cscope 的时候,它自动扫描当前目录之中的源文件,并把收集到的信息存储在一个内部数据库里面。如果需要递归扫描子目录,可以使用 -R 开关。如果你不需要 Cscope 的界面,只想从其它程序里查询其数据库,可以使用 -b 参数。如果你需要在一个大型或系统相关项目中使用,可以通过参考链接中的指南来查询一些优化参数,以提高速度。

缺省情况下,生成数据库之后,前端界面会自动启动 (可以使用 -d 参数告知 Cscope 使用已经生成的数据库,而不是重新生成一个)。这事一个两个面板的界面;在下面的面板中输入你希望查询的内容,结果会在上面的面板中显示出来。你可以使用 Tab 键在面板间切换,退出程序的快捷键是 Ctrl-D

在下面的面版上,可以使用方向键切换不同的查找域。使用这个面板,你可以:

  • 查找某特定符号的出现位置;
  • 查找全局定义 (如果找到的话,自动打开编辑器)
  • 查找特定函数调用过的函数
  • 查找调用某个特定函数的函数
  • 查找文本字符串
  • 替换字符串
  • 查找一个 egrep 正则表达式
  • 在编辑器里打开一个特定文件
  • 查找 #include 了某个文件的文件

每当你进行一次查询,Cscope 会把查找结果进行编号,和文件名、函数名 (如果有的话)、行号以及代码行本身一起显示出来。如果使用方向键选择了一个查询结果并敲回车或是直接敲对应的数字键,Cscope 会启动系统缺省的编辑器 (由 EDITOR 环境变量确定) 打开该文件,并把光标定位到该行 (某些编辑器可能不支持定位到行,不过至少 Emacs 和 Vim 没有问题)。

使用 (X)Emacs 作为前端

在 Emacs 中使用 Cscope 非常容易。如果你没有运行着 cscope 开头的程序,而 Emacs 中已经有 Cscope 菜单了,你可以通过安装 xcscope.el 在 Emacs 中集成 Cscope。xcscope.el 可以在 Cscope 源码包中的 contrib/xcscope 子目录中得到。安装的方法是把 cscope-indexer 脚本放到 $PATH 中的路径之中,并把 xcscope.el 放到 Emacs 的脚本路径 (路径相关帮助可以在 Emacs 里面运行 ``C-h v load-path`` 来查询 load-path 相关说明)。先在,把 (require 'xcscope') 这行放到 ~/.emace 或 ~/emacs.d/init.el 当中就可以了。xcscope.el 文件的开头部分的注释可以作为文档。


这个包把所有 Cscope 的查找命令添加导了 Emacs 菜单中的 Cscope 子菜单当中,并且可以在你编辑文件的时候使用快捷键调用。比如,如果你想查找一个符号,可以直接在菜单中选择 Cscope -> Symbol 或是输入 M-x cscope-find-this-symbol,或按快捷键 C-c s s,之后输入符号的名字 (如果什么都不输入,就使用光标下的名字)。搜索的结果会显示在 *cscope* buffer 之中, 按照文件名分组,并以 <函数名>[行号] <整行内容> 的形式显示。把光标移动到想查看的搜索结果上,按空格键,将会在另一个 buffer 中打开该文件,并定位光标到搜索的行。如果你按的是回车而不是空格,你将会直接从 *cscope* buffer 中跳到相应的 buffer (鼠标点击搜索结果也可以)。你可以使用 n 和 p 来选择下一个或上一个搜索结果 (当 *cscope* buffer 不是当前 buffer 的时候可以用 C-c s n 和 C-c s p)。N 或 P 可以用于选择下一个和上一个文件 (或 C-c s N 和 C-c s P)。

在 Vim 中使用 Cscope

如果你更喜欢用 Vim,你还是可以用 Cscope。首先,你的 Vim 应该是使用 --enable-cscope 开关编译的。大部分二进制形式的 Linux 发布版都打开了这个开关。Gentoo 的用户则应该打开 cscope USE 标志。这里假设你使用的是 Vim 6.x 或 7.x。Vim 参考手册里包含了一篇使用 Cscope 接口的文章,你可以在 /usr/share/vim/vim&version/doc/if_cscop.txt找到它。你还可以看另一个简短的教程 (参考链接)。


在 Vim 中,你可以使用如下形式调用 Cscope: :cscope find search type search string (可以用 :cs f 来代替 :cscope find),这里的 search type 包括:

  • symbol or s -- 所有引用这个符号的地方;
  • global or g --查找全局符号
  • calls or c --查找特定函数的所有调用
  • called or d --查找特定函数调用的所有函数
  • text or t --查找文本
  • file or f --打开文件
  • include or i --查找 #include 了指定文件的文件
查找结果会在 Vim 窗口的底部以菜单方式显示出来。你可以键入你希望进入的查找结果的编号并按回车。如果你用 :scscope 或 :scs 代替 :cscope 的话,Vim 窗口会水平拆分成两个,你选择的查找结果将会放在新的窗口之中。

在 Vim 之中,从 Cscope 查询中跳到一个结果和跳到任意的 tag 没有什么区别; 你可以用 Ctrl-T 条回到查找之前的地方,也可以用 :tnext 和 :tprevious 在查找结果间来回跳。


如果你想调对光标下的词进行查找,你应该安装 cscope_maps.vim 插件 (把这个文件放在 $HOME/.vim/plugin 目录即可)。这个文件里面的注释说明了它的用法。使用这个插件,你可以用 Ctrl- 代替 :cscope,用 Ctrl-space 代替 :scscope,搜索将意光标下的词作为搜索词 (比如,你把光标挪到 "initialize" 上面,输入 Ctrl- s,就可以找到所有引用 initialize 符号的地方了。


SilentBob

SilentBob 是一个用于分析源代码的新工具,目前支持 C/C++, Perl 以及 Python,不过它的插件框架 (目前尚无文档)允许用户方便地添加新语言和新功能。


你可以从该软件的官方网站获取源码包或 deb 包。安装之后,在源码目录运行三次 SilentBob:

  bob --make-ctags
bob --cfiles
bob -L cfiles --call-tags
这样会生成三个文件: tags, 一般标签表格; cfiles, C/C++ 文件列表; calltags, 调用标签表。 调用标签表用于函数调用,所以,如果你希望查找某个函数的所有调用,你可以让 Vim 使用 调用标签表 (:set tags=./call_tags) 并使用内建命令用于查找标签 (:tag function-name 以及用 :tnext:tprevious循环查找)。这三个索引文件可以被 SilentBob 用于构建调用树和反向调用树。


对于 Perl 和 Python,只支持标签表和文件列表:

  bob <--perl | --python> --make-ctags
bob <--perl | --python> --files
第二个命令会生成 generate a perl_filespython_files 文件。


一旦生成了一个标签表,SilentBob 可以显示出一个调用树:

  bob [--depth N] function 

--depth 选项允许你限制调用树的深度。如果你之希望知道哪些函数被给定函数调用了,使用 --depth 0 参数即可。否则,被调用的函数会被依次列出来。


注意,你可以对 SilentBob 为 Python 和 Perl 文件生成的标签表加上这个参数。不过,使用 Exuberant Ctags 生成的表是不被支持的。


调用标签表还可以用于生成反向调用树

  bob [--depth N] -u function 

这将依次显示调用给定函数的函数。这时,指定 --depth 1 则只显示调用此函数的函数。SilentBob 也可以使用创建的 cfiles 文件查找 C/C++代码种的文本。它检查操作符,字符串和注释会被省略掉。

  bob list of files --cgrep pieces of text, separated by comma 

你可以指定 -L ./cfiles 来使用生成的文件列表。几个文本应该来自于同一个操作符,所以,如果你要找检验 T 变量的地方,可以使用:

  bob -L ./cfiles --cgrep if,T
SilentBob 还包含一个 tags 工具,让你可以在一个控制台查看标签的定义。调用 tags tag1 tag2 ... tagN 可以从代码中取出你感兴趣的片段 -- 函数定义、全局变量声明等等 -- 你将会看到你需要的代码片段。

为什么使用 SilentBob 生成标签?

SilentBob 使用语法分析器来解析源文件,这使得它比使用正则表达式定位文件中的某行的工具,如 Exuberant Ctags 要快很多。在对 Linux 内核源文件 (2.6.19) 的测试中,Exuberant Ctags 生成标签表需要 90 秒,而 SilentBob 仅需 10 秒钟 (测试机使用 2.6GHz 的赛扬处理器)。SilentBob 还支持多线程优化。

另一个不同来自于标签表的格式: Exuberant Ctags 生成的表中,使用正则表达式定位特定行。这就意味着,如果你编辑该文件,某些定义的位置可能会改变,但你不需要重新生成标签表。这对于 Exuberant Ctags 来说很理想,因为这样你就不需要频繁地重新生成表格了,不过,这也意味着如果你在浏览一个大型文件,在标签定义之间的跳转相对于记录行号的方式会非常慢。这就是 SilentBob 为什么在标签表中使用行号; 不过,这就意味着你必须在较大的编辑之后重新生成标签表了。

参考链接

  1. "tags" - http://applications.linux.com/article.pl?sid=07/01/22/167212&tid=13
  2. "Cscope" - http://cscope.sourceforge.net/
  3. "在大型项目中使用 Cscope" - http://cscope.sourceforge.net/large_projects.html
  4. "关于在 Vim 里使用 Cscope 的简短教程" - http://cscope.sourceforge.net/cscope_vim_tutorial.html
  5. "cscope_maps.vim" - http://cscope.sourceforge.net/cscope_maps.vim
  6. "SilentBob" - http://silentbob.sourceforge.net/

写了一个LDAP教程

很简单地介绍了 LDAP 的概念,和数据库、NIS 的对比,在 PAM, Apache 里面的应用等等。

在这里可以下载到打印版:
http://gnawux.googlepages.com/ldap.handout.pdf

用 beamer 写的。

Monday, March 12, 2007

[译文] Wiki 企业应用之演化


http://www.linuxinsider.com/rsstory/56207.html


为避免错误的编辑操作,wiki 所引入的另一个功能是健壮性的修改控制机制和审计手段。这些机制不紧包括谁修改了、从某个页面添加或删除了什么,通常还包括获取变更历史以及为了检查而取出较早版本等。



最近,Mismo 通过安装了一套称为“wild”的最新 Web 系统来之成了它的信息基础设施。大部分的读者可能听说过自由的在线百科全书 Wikipedia,这个最著名的这种 web 技术的实例。我想我可以介绍一下这种技术以及如何可以在你的组织之中使用这种技术来作为一种知识管理。

协作效用 (Collaborative Effort)

Wikipedia 是这么定义 wiki 的: “一个允许访问者便捷地自行添加、删除、编辑、修改内容的网站,通常情况下,上述操作甚至不需要注册。交互与操作的便捷性使得 wiki 成为了一个高效的大型共同写作工具。”


该网站还记述: “Wiki 这个名词通常也用于指代支持上述网站运营的协作软件本身 (wiki 引擎),或指代某些特定的 wiki 站点,如计算机科学站点 WikiWikiWeb (最早的 wiki) 和在线百科全书 Wikipedia。”


本质上说,wiki 是一个支持内部链接 Web 服务器应用,交叉组织着一个可以不断扩充的信息集。Wiki 中一个包含某个特定主题的特定页面被称为一篇“文章 (article)”。


而使一个 Wiki 独一无二的正是网站中所包含的内容和这些内容到内部的其他文章之间的链接。


以 Wikipedia 为例,一篇关于加利福尼亚的文章会链接到该州首府萨克拉门托的一个页面。


传统的 wiki 之中,"驼峰词" (形如 UpperCamelCase) 会自动链接到另一个主题或文章。大多数情况下,拥有帐号的任何人都可以访问、修改或编辑一个页面。这是 wiki 的又一个特有的特征。


所有的内容都是用户创建的。这让 wiki 网站的内容成为“社区共有”的。这页同时允许了恶意用户来登录并篡改内容,这在 Wikipedia 上曾经发生过。


为避免错误的编辑操作,wiki 所引入的另一个功能是健壮性的修改控制机制和审计手段。这些机制不紧包括谁修改了、从某个页面添加或删除了什么,通常还包括获取变更历史以及为了检查而取出较早版本等。大多数时间,wiki 也提供强健的主题和全文搜索能力。

企业级应用 (Enterprise-Level Use)

没有设么理由会组织你把这项技术用于企业。通常情况下,你会利用 wiki 存储一些需要多个实名帐号访问更新其内容的技术文档。


Wiki 不是一个文档共享平台,不能用与诸如微软 SharePoint 等软件来合作。它也不是一个用于文档和源代码管理的版本管理系统 (诸如 CVS 或微软 Visual SourceSafe)。它是一个内容共享系统,良好地组织内容之间的关系。


如果你的组织中有多人添加、维护的协作知识库是,并且这些知识是相关的,这种情况下,你就可以考虑使用 wiki 了。


一个典型的例子就是软件公司中的开发方法。每个公司有自己的不同的软件生命周期模型和开发过程,通常这个模型还是不断演化的。对于一个放贷者,风险或贷款准则也是一个例子,其中的各种名词是相关的,并且一组业务员可能共同负责内容的修订。


Wiki 软件既有自由版本也有商业版本——其选择依赖于你想得到些什么。对于我所知道的大多数工业界的案例,诸如 JSPWiki 之类的自由软件就足够了 (包括 Mismo 的案例)。

简与繁 (Simple and Complex)

Mismo 使用 wiki 来存放、更新他们的工程守则。工程守则由所有的导师所共同创作,来成为一个工业标准。这些守则可以非常简单 (如使用全大写字母和下划线作为容器名称的命名常规),也可能相当复杂 (如 Mismo 如何使用 XML 名字空间第三版)。


这是当前 Mismo 工程守则的一个列表,有的还在起草中:

  • Mismo business terminology
  • XML profile
  • Namespaces
  • Unicode
  • Class words
  • Approved acronyms
  • Mismo technical terminology
  • Filenames-namespaces
  • Attribute and element names
  • Personal information meta data tag
  • Document type definition (DTD) and zero-delta schema
  • Implementation guides
  • Document data mapping
  • Embedded file profile

要访问Mismo wiki, 可以去这里 wiki.mismo.org/mismowiki.


如果你想在个人层次上研究 wiki 技术,看看 TiddlyWiki 吧。这是一个很不错的、自完备的 wiki,使用 html 来保存所有东西,非常易于迁移。我使用它来作为个人笔记和技术文档工具。


© 2007 Mortgage Banking. All rights reserved.
© 2007 ECT News Network. All rights reserved.

Monday, March 05, 2007

mutt 转发邮件的设置

缺省情况下,mutt 是把邮件原文引在正文里,然后转发的,并且缺省不带有附件,而我们很多时候更喜欢把原来的整个邮件作为附件转发,这个可以通过在配置文件里加入下面两行来实现:

set mime_forward=yes
set mime_forward_rest=yes

参考: Mutt FAQ

Mutt 中自动显示 word 文档

部分地继承了王垠的设置,有一点点改进。

通过使用 wvHtml 可以把 doc 转换成 html,然后浏览,下面是 ~/.mailcap 设置
application/msword; wvHtml --charset=utf8 %s - | w3m -T text/html; nametemplate=%s.doc; copiousoutput
不过,有的时候,MIME 会显示 doc 附件为 application/octet-stream ,这时可以让 mutt 进一步判断 MIME 类型,在 mutt 配置文件中写:
mime_lookup application/octet-stream
就可以了。

参考,王垠的介绍,还有就是 mutt 用户手册。

Mutt 中根据编码不同,自动用不同命令显示附件内容

很多邮件是 HTML 的,不过这些 HTML 只包含 HTML 语法,并不包含字符集提示等等内容,所以,如果这些 HTML 直接交给 w3m 或 lynx 处理,能否正确显示是要看运气的,我们不可能假设别人发来的邮件是相同编码的,更要命的是,很多情况下,根据内容无法区分 gb 编码和 latin-1 编码,乃至 utf-8 编码。

好在 mutt 会把 MIME 参数传送给 mailcap 的处理语句,这样,比如
Content-Type: text/html; charset=gb2312
这个 charset 也会作为变量 %{charset} 传送给命令行,所以,我们在 ~/.mailcap 里面设置
text/html; w3m -I %{charset} -T text/html ; nametemplate=%s.html; copiousoutput;
就可以把任意 text/html 内容转换成 utf-8,然后用 w3m 显示。

参考文献: 《Mutt 用户手册》第五章。

Sunday, February 18, 2007

新年许愿

新年到了, 许几个心愿吧
  1. 改几个坏毛病, 嗯, 尤其是自己的时间管理方面, 提高一点自制力.
  2. 为求学生涯划上一个好看的句号.
  3. 为职业生涯开个好头, 找到一份好工作.
  4. 完成我的 linux 书.
  5. 来一个甜蜜幸福的婚礼.

新年, 新生活

Sunday, February 11, 2007

[译文] 使用加密工具提高系统安全性

http://security.linux.com/article.pl?sid=07/01/31/1539208&from=rss

我的 U 盘里总会放着一份 Bcrypt. 这是个极为简单易用的基本工具。一旦装上了 bcrypt, 你惟一要做的就是在命令行依次输入 bcrypt 和你要加密的文件名。之后,Bcrypt 会要求你提供一个密码,仅此而已。加密之后,Bcrypt 会给文件加上 .bfe 的扩展名。同样的命令也可以用于解密,bcrypt 仅仅通过文件的扩展名来决定是要加密还是解密。

Bcrypt 使用 Blowfish 。算法。密码通常要有 8 到 56 个字符,并被内部哈希为一个 448 位密钥以增强安全性。缺省条件下,加密文件的时候,原始文件将被删除并在原来存储文件的位置覆写 3 次,以避免通过反删除工具发现原始文件,你可以增加或减少重写的次数。

Bcrypt 缺乏灵活性和各种开关,所以可能不是你加密军火库中的首选武器,不过,简单是它的强项。根据 Bcrypt 的项目网站介绍,它可以用于 Linux 和 *BSD, 没有 Windows 版本; 不过,这个网站似乎有年头没更新过了。

Ncrypt

Ncrypt 是另一个简单的文件加密/解密程序。你可以选择三个 AES 加密标准候选加密算法: Rijndael, Twofish, 和 Serpent 中的任何一个。开发者特别注意了生成密码的安全性: 当一个文本密码被用于加密文件的时候,它首先被转换为 SHA-1 哈希值,而原文被立刻清除出内存。之后,这个哈希值被用于密钥,随后,也会被清除出内存。

Ncrypt 同时有 Unix 和 Windows 版本。它的用法很直接: 使用 ncrypt 命令,用开关选择加密算法,是要加密、解密、还是要清除文件,以及输入输出文件名。。原始文件将被从磁盘上彻底清除;Ncrypt 也有一个非常有用的文件清除功能,你可以用它安全删除文件。

Pad

与 Bcrypt 和 Ncrypt 不同,Pad 使用 on-time pad (OTP) 加密。一个文件会被分成两个乃至更多独立的"pads", 没一个都类似于白噪声。两个文件看起来只是混入了无害的随机数据,可以在用户喜欢的任何时候被重新组装起来。

OTP 有非常悠久的历史了。理论上讲,它是惟一真正不可破解的加密手段。不过,它有一些实际应用上的弱点: 每个 pad 尽可以被使用一次,而且必须是真正的随机数 (这实际上非常困难),并且它很容易受到中间人工具。这样,它不被推荐用于日常加密任务。不过,有一个场合下,OTP 被认为是有价值的: 自由语音加密。比如,如果有人希望自由分发一个机密文件,它可以将文件拆成不同的 pad,并将多个部分存放在不同的一同里,并告诉别人如何获取它们并组合成原始文件。(译注: 这段翻译的不怎么好,因为译者根本不懂什么是 OTP, 查了半天还是不怎么明白,欢迎解释。)

GnuPG

对于多数人来说,GnuPG 是开源文件加密的不二选择。一些发布版还把它随发布版预装。引用其 FAQ 中的原文,"GnuPG 代表 GNU 隐私卫士,是用于安全通信与数据存储的 GNU 工具。它可以被用于数据加密和创建数字签名。它包含一个先进的密钥管理工具并与 RFC 2440 所描述的 OpenPGP Internet 标准提案相兼容。因而,它的目标是兼容 NAI 公司的 PGP。."

Bcrypt, Ncrypt 和很多其它加密工具使用对称密钥加密文件。而 GnuPG 和 PGP 一样,使用公钥密钥加密,尽管它也支持对称加密。公钥加密使得加密和签名多个文件并和其他用户交换它们变得很容易。对于对称密钥和公钥密钥的综述以及它们的工作机制,可以参考 GnuPG 手册的第二章和 FAQ 的 7.1 节。

GnuPG 可以独自地作为命令行工具使用,它有很多功能,并可以满足各种挑剔的用户。不过,它也有各种不错的前端工具可用。其中,我所用的是 KGpg, 集成在 KDE 之中,这方便了我很多日常加密工作。比如,其它我提到的加密工具只能加密文件,而不能加密目录。你可以用 KGpg 加密目录中的所有文件,或者创建一个 .tar.gz 或是 .zip 文件,并对它进行加密 。使用 KGpg, 我只要双击一个目录并告诉程序打包加密之即可。KGpg 也允许你在桌面创建一个碎纸机,用于安全删除你放在里面的文件 (而不是目录)。这非常方便,尽管我建议你阅读作者的关于破碎文件的安全说明。KGpg 的易用性非常优秀;即使对新手来说,学习曲线也非常短。

GnuPG 的开发步伐非常文鼎,而且支持多种操作系统。它在多种 Unix 系统上都可以编译,而且通过 Gpg4Win 提供了 Windows 移植版本。对于 Unix 系统的邮件加密的支持性也非常可靠: 查询 GnuPG FAQ 的 4.15 节,可以看到提供 GnuPG 集成的邮件客户端的列表 (很遗憾,支持 OpenPGP 标准的 Windows 客户端十分少见)。关于更多的邮件工具,可以看看 Aegypten 项目。

关于加密的更多信息,两个不错的起点是对应的 Wikipedia 文章和 Cryptography FAQ.

Rui Lopes 是一个葡萄牙网页设计师和独立纸片人,在技术领域有广泛兴趣。


Wednesday, February 07, 2007

发现一个兼容性问题

Firefox 3.0a2pre 和 Google Pages 是有矛盾的,用了前者,后者的被编辑页面内容是空的。

降级回到 Debian Sid 的 Iceweasel 2.0.0.1 (也就是 Firefox 2.0.0.1) 才解决了问题,啥都正常了。

Wednesday, January 03, 2007

应用层再分层

偶真伟大阿,这种东东都敢想,哈哈

对很多应用层应用案例,可能可以分三个子层面,暂时按照王氏命名法,命名为

语义子层 semantics
表达子层 express
传输子层 transport

传输子层包含应用层信令, 传输内容的规格、长度等,例如 HTTP, SMTP 等
表达子层是应用层内容的基本表示形式、语法表达规范等,例如 MIME/Base64, XML 等
语义子层是应用层内容的与语义相对应的具体语法格式,例如 XHTML, RDF 等

对于传统的协议,可能有的协议会对应其中的多个子层,嗯,呵呵

偶也不知道 SOAP, SDP, WSDL 啥的到底应该怎么对应,不过,应该能对应上吧,至于那些不能对应的,呵呵,偶因为还不清楚,说不好怎么弄