正在加载...

Fedora Linux Toolbox翻译小记

六月 3rd, 2010

缘起:谈我与计算机翻译图书的二三事——图灵五周年馈赠活动之一

中文版《Linux命令详解手册》2009年9月第1版,勘误地址:http://goo.gl/rskK

2008年10月16日,因审读Embedded Linux Primer而结识的傅编辑来邮,询问有无兴趣接手Fedora Linux Toolbox一书的翻译。在这之前已与其他人合译过几本技术书,翻译过程,五味杂陈,收获良多,失之不少。那时已暗下决心,今后再有机会译一本Linux内核,外加一本非技术书,别无他求。

当时心里着实矛盾了一阵。找编辑要了英文电子版,看看内容是否吸引自己。几天之后,考虑再三,决定接手,一为献给18日刚出生的女儿,二为可以独自完整译一本书,而且是Linux方面的,也算遂了一部分心愿。和编辑约定好大致的交稿时间,三个月(2009年1月底交稿)。休完母婴照顾假,回公司上班,签订翻译合同。

2008年12月中旬,编辑询问进度,大概完成全书1/3。初为人父的喜悦完全占了上风,外加照顾开心妈妈,有时几天译不了一页。所幸,有外婆里里外外的照顾,开心妈妈的母乳喂养,当了爸爸的我还能得不少空闲,但是进度完全不受自己的掌控。

2009年1月中旬,主动向编辑坦白,可能要延期0.5~1个月,春节赶工的话,2月1日交初稿。

2009年2月16日,邮出初稿PDF文档(OpenOffice.org转换);3月13日,邮出正文译文v0.9,索引/前言v1.0a;3月23日,1-6章v1.0b。编辑询问部分译文加底纹是何意,答:一校存疑/待润色(蓝底黑字),原文错误/根据上下文修改(红底黑字),译注/补充内容(灰底蓝字)。

2009年4月7日,邮出v1.0b,包括1-9、11-12章及附录A、B,询问编辑译稿后期处理流程,译文再有更新如何处理。4月13日,邮出前言、正文、附录最终稿,PDF/DOC文档(OpenOffice.org转换)。

2009年5月23日,邮出v1.0.1。与执行编辑讨论译稿的局部修改和润色,宣传文字。

2009年6月8日,通过Google Docs回答编辑提出的译稿相关问题(这次整理邮件,才发现编辑用的书名是《Linux命令速查》而非《Linux命令详解手册》)。6月24日,更新第8章、索引,修正几处硬伤。6月26日,更新11、13章,修正几处硬伤。6月29日,提供最新译稿,主要更新第9、10、12、14章,多半为硬伤。

2009年7月23日,经过半月,译者序仍未完成。7月28日,邮出译者序,可惜拖延太久,编辑回复已出片,所幸还能加上献词。

2009年10、11月,拿到样书,通读全书,制订勘误表。

总结出错原因:

  1. 译文本身翻译不当
  2. 已修正原版大部分错误(主要通过上下文),仍有部分遗漏
  3. 排版过程中引入的字体不一致、多余空格、大小写有误等问题
  4. 排版所用译文与译者提供的版本不一致(很大程度上应由本人负责,未及时定稿,后期更新过于频繁,给编辑和审校增添不少麻烦)

2009年12月,同编辑确认稿酬支付事宜。

原定3个月的计划,全书翻译加上定稿却用了8个月+,一本两百多页的书,前前后后历经一年多。从完成时间看,几无进度控制,当然责任主要在我,当初制定计划,完全低估了小家伙的魅力,错误估计第二年公司日常工作的强度。进入2009年,一周六天,基本上每天晚上九十点之后,才能开始翻译工作,周日又要带着小家伙外出。回头来看,接手这类翻译活儿,除了兴趣,一定要预估自己时间是否充裕,切不可太过乐观。

翻译后期,全书译文来回校了几遍,但效率并不高,只怪初稿翻译太过匆忙,以致后期忙于打补丁。另外,搭建系统环境测试书中命令,只验证了大约过半;时间拖得太久,热情渐失,原本计划的Ubuntu 8.04或8.10发行版命令验证,最终也不了了之。

整个翻译工作使用了如下工具:OpenOffice.org,谷歌金山词霸合作版,有道词典,Google。

乐铺活动验证

在Makefile函数里定义目标

十二月 28th, 2009

最近同事调试一个新平台,在编译平台软件时,make始终无法成功完成,两个人折腾一番之后,最终确认了老版本make无法识别Makefile某些新写法。

测试用Makefile如下:

   1: # Supported since make v3.81
   2: WHO := $(sort jack andy)
   3: V=@
   4:  
   5: all: $(WHO)
   6:  
   7: # target defined in function
   8: define compile_template
   9: $(basename $(1)):
  10:    $(V)echo "hello$(1)!"
  11: endef
  12:  
  13: $(foreach var, $(WHO), $(eval $(call compile_template, $(var))))

同事还在用RedHat 9,make版本v3.79,v3.80。

《Linux命令详解手册》勘误

十月 7th, 2009

Linux命令详解手册》勘误

Fedora® Linux® TOOLBOX: 1000+ Commands for Fedora, CentOS and Red Hat Power Users

说明:本勘误仅对以下版本有效。欢迎各位批评指正,协助维护本勘误,勘误建议或编辑权限申请可邮至fedora.linux.toolbox@gmail.com

勘误地址:http://docs.google.com/View?id=ajghxkgt669z_121cvfczsfc

【作  者】 Christopher Negus; Franois Caen

【译  者】 李琳骁

【丛 书 名】 图灵系统与网络管理技术丛书

【出 版 社】 人民邮电出版社     【书 号】 9787115211330

【上架时间】 2009-9-11

【出版日期】 2009 年9月 【开 本】 16开 【页 码】 246     【版 次】1-1

错误来源:

  • 译者翻译不当
  • 英文版的错误大部分已在翻译时做了修正(主要通过上下文推断),但仍有部分遗漏
  • 排版过程中引入的字体不一致问题
  • 排版所用译文与译者提供的版本不一致

开心日记

七月 8th, 2009

小家伙快九个月了,白粥、玉米糊等辅食仍一概无视。拿着小块面包,大人张嘴“索要”,小家伙倒往大人嘴里放,小可人儿,爸爸妈妈可是宁愿你自己大口大口的吃。

小家伙的主食仍是母乳,以前半个一个小时的吃,现在十几二十分钟就能搞定,妈妈也稍稍轻松了些,但晚上还是很累,隔一段时间就得观察一下小家伙,是不是抱着外婆做的被子舔的津津有味。在吃喝上,开心的第二爱好是开水,咕咚咕咚能喝下五六十毫升,当然,喝得多,漏的也多。:)


周日傍晚,全家游西湖,自西泠桥,一路风景,满塘荷花,行至放鹤亭,小家伙饿了,找了面朝白堤的长椅,大人们围坐一起,小家伙就吃起奶来,双眼紧闭,冷落着跟前的绿叶荷花。小家伙饱了,基本上就睡熟了,这是开心的习惯。

爸爸抱着,石板踏着,知了声声,柳条飘飘,小家伙睡的香吧。出了孤山后山路,把小家伙放到推车里躺着,大人推着车,过锦带桥,未及断桥,车里的小家伙仰着头想起来了,这么热闹,怎能错过。

诡异的mount()

五月 23rd, 2009

最近在2.6.10内核下调试硬盘分区(FAT32文件系统)保护功能,为保护FAT表、根目录和目录项等重要区域,应用程序不得操作这些区域,其中一项就是禁止更新文件访问时间(会更新目录项),使用mount()系统调用时却出现诡异现象。

[ 测试代码 ]

   1: int main()
   2: {
   3:     ... 
   4:  
   5:     mount("/dev/sda1", "/mnt/sda1", "vfat", 0, NULL); 
   6:  
   7:     ... 
   8:  
   9:     /* 读/写sda1分区里的文件 */ 
  10:  
  11:     sync(); 
  12:  
  13:     return 0;
  14: } 

[ 内核修改 ]

   1: /**    -> fs/inode.c
   2:  *    update_atime    -    update the access time
   3:  *    @inode: inode accessed
   4:  *
   5:  *    Update the accessed time on an inode and mark it for writeback.
   6:  *    This function automatically handles read only file systems and media,
   7:  *    as well as the "noatime" flag and inode specific "noatime" markers.
   8:  */
   9: void update_atime(struct inode *inode)
  10: {
  11:     struct timespec now; 
  12:  
  13:     if (IS_NOATIME(inode))
  14:         return;
  15:     if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
  16:         return;
  17:     if (IS_RDONLY(inode))
  18:         return; 
  19:  
  20: +    if (inode->i_sb) {
  21: +        if (!strcmp(inode->i_sb->s_type->name, "vfat"))
  22: +            __backtrace();
  23: +    }
  24:     now = current_kernel_time();
  25:     if (inode_times_differ(inode, &inode->i_atime, &now)) {
  26:         inode->i_atime = now;
  27:         mark_inode_dirty_sync(inode);
  28:     } else {
  29:         if (!timespec_equal(&inode->i_atime, &now))
  30:             inode->i_atime = now;
  31:     }
  32: } 

测试程序第一次执行时,内核会打印如下调试信息:

   1: <4>Function entered at [<c009443c>] from [<c005bc18>]      /* c009443c T update_atime */
   2: <4> r6 = 00000000  r5 = 00000000  r4 = 00000200 
   3: <4>Function entered at [<c005b6c4>] from [<c005e2b8>]      /* c005b6c4 T do_generic_mapping_read */
   4: <4>Function entered at [<c005e0c0>] from [<c005e41c>]      /* c005e0c0 T __generic_file_aio_read */
   5: <4>Function entered at [<c005e388>] from [<c0078114>]      /* c005e388 T generic_file_read */
   6: <4> r9 = C3026000  r8 = C3027F78</span>  r7 = C005E388  r6 = BEFFF560
   7: <4> r5 = C3CE0A80  r4 = 00000200 
   8: <4>Function entered at [<c0078050>] from [<c0078360>]      /* c0078050 T vfs_read */
   9: <4> r8 = C0025154  r7 = 00000003  r6 = C3CE0A80  r5 = 00000000
  10: <4> r4 = 00000000 
  11: <4>Function entered at [<c0078318>] from [<c00249c0>]      /* c0078318 T sys_read */
  12: <4> r6 = 00000200  r5 = BEFFF560  r4 = 00000003            /* 注释部分结合System.map文件得到 */

接着修改测试代码的mount()调用:

   1: -    mount("/dev/sda1", "/mnt/sda1", "vfat", 0, NULL);
   2: +    mount("/dev/sda1", "/mnt/sda1", "vfat", MS_NOATIME, NULL); 

编译并再次执行测试程序,内核仍打印上面的调试信息,着实让人摸不着头脑。重启Linux系统,执行修改后的测试程序,内核便不再打印上述调试信息!

……

复查测试代码,查看mount()手册页,看到下面几段说明(man-pages 2.77):

MS_REMOUNT
  Remount an existing mount.  This allows you to change the mountflags and data of an  existing
  mount without having to unmount and remount the file system.  source and target should be the
  same values specified in the initial mount() call; filesystemtype is ignored.

  The following mountflags can be changed: MS_RDONLY, MS_SYNCHRONOUS, MS_MANDLOCK;
  before  kernel 2.6.16, the following could also be changed: MS_NOATIME and MS_NODIRATIME;
  and, additionally, before kernel 2.4, the following could also be changed: MS_NOSUID,
  MS_NODEV, MS_NOEXEC.

聪明的你,想到问题在哪儿了吧。:P

A little learning is a dangerous thing

三月 11th, 2009
  1. 浅学误人
  2. 毋识毋惊,全识全惊
  3. 一知半解,害人不浅
  4. 学识浅薄是件危险的事情
  5. 学艺不精反误事
  6. 一知半解最危险
  7. 一知半解,害已误人
  8. ......

John Bartlett (1820–1905). Familiar Quotations, 10th ed.  1919.



NUMBER:3484
AUTHOR:Alexander Pope (1688–1744)
QUOTATION:A little learning is a dangerous thing; 1
Drink deep, or taste not the Pierian spring:
There shallow draughts intoxicate the brain,
And drinking largely sobers us again.
ATTRIBUTION:Essay on Criticism. Part ii. Line 15.
BIOGRAPHY:Columbia Encyclopedia.

FAT文件系统分析相关资料

三月 11th, 2009

前阵子处理FAT32文件系统和硬盘相关的任务,主要参考下面这两份资料:

  1. The FAT File System: FAT
  2. 透彻分析FAT文件系统!(一)

第二份资料尤其有用,详细分析了FAT文件系统在硬盘上的扇区布局。

告别电信CDMA

三月 9th, 2009

前日,手机游下水道去了,还是挂我名下唯一一个CDMA号,于是准备补卡。


一进电信营业厅,好家伙,和省妇保医院有的一拼,临门口齐刷刷坐了几排人等着办理业务,立马打消继续等的念头,随手取了个号:时间12:03,116号,前面还有33人。整个营业厅有两名营业员负责办理业务。顺道回家吃午饭,半个多小时后,回到营业厅,提示正在处理92号。…………浏览了十几段新闻,十几分钟,两名营业员分别处理着两个业务。……13点13分,“漫长”的等待,终于叫到116号。补卡要50¥,或者充100¥免费换一张,当即决定注销号码,登记单上印着受理时间:13时20分。

1. 80分钟x2=160分钟,刨去期间因各种原因不等继续等的号5~10个,取8,处理25个号,6.4分钟/号;
2. 已叫过的号无应答,之后又允许插队,电信自己制订规则又破坏规则;
3. 补SIM卡要50¥,或者充值100¥(免费补卡吧?)。nnd,我要没带那么多钱,为了送钱改天又得扔上个把小时?(记得移动前两年只需充值50¥即可免费补卡,现在一年免费补一次卡)
4. 两名业务员兼卖充值卡,买充值卡不需要叫号……电信很重视“现金流”,值得称赞。
5. 销号仍扣除当月月租(预缴),管它什么月初月末,60天后凭身份证原件领取余额。

算了,没心情继续陪电信玩。

History of the Internet

一月 9th, 2009


History of the Internet from PICOL on Vimeo.

来源

都是指针惹的祸?(一)

一月 7th, 2009
   1: /* slightly modified, for 32-bit platform */
   2:  
   3: #define MAX_INDEX                   0x8
   4: #define IOCTL_GET_FOO_STRUCT        0x20081018
   5:  
   6: struct foo_s {
   7:     int bla;
   8:     int blabla;
   9:     /* .... */
  10: };
  11:  
  12: struct foo_s foo_structs[MAX_INDEX];
  13:  
  14: /*
  15:  * 获取内核指定数组中索引为index的元素,用户层传入的缓冲区结构如下:
  16:  * 
  17:  * ,--------------------,
  18:  * |     u32 index      |  sizeof(u32), 0-based
  19:  * |--------------------|
  20:  * |    struct foo_s    |
  21:  * |        ...         |
  22:  * `--------------------`
  23:  *
  24:  */
  25:  
  26: static int foo_ioctl(struct inode *inode, struct file *file,
  27:         unsigned int cmd, unsigned long arg)
  28: {
  29:     /* .... */
  30:  
  31:     switch (cmd) {
  32:         /* .... */
  33:  
  34:         case IOCTL_GET_FOO_STRUCT:
  35:             {
  36:                 unsigned long not = 0;
  37:                 u32 *ip = (u32 *)arg;
  38:  
  39:                 printk(KERN_INFO "get index %d\n", *ip);
  40:                 if (*ip >= MAX_INDEX) {
  41:                     return -EINVAL;
  42:                 }
  43:                 check_foo_present(*ip); /* check if the struct valid */
  44:                 *ip = IOCTL_GET_FOO_STRUCT; /* take it as magic */
  45:                 not = copy_to_user((void *)(arg + sizeof(u32)), /* offset! */
  46:                         &foo_structs[*ip], sizeof(struct foo_s));
  47:  
  48:                 break;
  49:             }
  50:  
  51:             /* .... */
  52:  
  53:     } /* switch */
  54:  
  55:     return 0;
  56: }
  57:  

注意44~46行。

google reader 抓虾
bloglines my yahoo
哪吒 鲜果
* 更多订阅本站方式请看 订阅帮助