分类 编程相关 下的文章

台风“巨爵”离去后,今晚又恢复如常的看书计划。《高质量程序设计艺术》来到第6章了,本章主要探讨程序的可移植性问题。

可移植性主要面对的几个难题是:操作系统、处理器体系结构、编译器与语言特性、图形界面环境、区域(如:显示多语言)、硬件设备与平台等方面的差异。提高程序的可移植性,主要就是解决以上几个难题。

解决可移植性的常用方法是使用一个代码层来对功能进行抽象,这实际上将差异性用一部分代码隔离了。例如:JavaScript的话,可以编写通用方法来获取屏幕大小,而该方法是通过判断不同浏览来调用不同的方法来实现。又例如:C/C++可以使用预处理。

 本章用了较大的篇幅探讨了图形界面的问题。值得注意的有以下几点:

1)字符编码应该采用更通用、兼容性更高的UTF-8,而不是特定于某个区域的编码。虽然GB1080已经提高了其兼容性,但面向国际的话,还是很勉强。

2)程序/软件中的消息,应该与代码分离,作为独立的、容易替换的资源来处理,以简化其本地化的工作。

3)可移植GUI(图形用户界面)除了可以考虑建立可移植层(如建立统一的API,分别在Windows和X上封装实现该API,程序便可该API)、采用仿真层(好象就是WINE的做法)、基于可移植层的平台(如Java的Swing、SWT等)以外,还可以考虑使用HTTP/HTML或AJAX层来提供用户界面。

首先,今天是个很特别的日子,因为很多情侣特意选择今天结婚(09年09月09日,有长长久久之意)。

废话说完。《高质量程序设计艺术》终于完成第5章了。第4章时间性能和第5章空间性能,其实可以合起来,就是程序优化的问题。首先,程序的时间性能跟空间性能,可以说是矛盾的,因为很多时候都是空间换时间,或者时间换空间。其次,程序优化,就有可能导致可移植性降低。所以,很多专家都认为,程序优化的首要准则是:不要优化(出自Michael A. Jackson)。当然,前提是该程序已经一个良好的程序(不懂怎么表达,反正就是好程序最好不要优化)。

优化的另一个指导思想是帕雷托法则(Pareto Principle)。本来是用在经济学问上的,而用在程序执行上表明,20%的代码通常占用了80%的执行时间。那么,只要找出这20%的代码,就可以对程序进行优化了。

优化的方法嘛,不外乎那几种:空间换时间、减少I/O操作、降低算法复杂度等等。

对于空间性能方面,由于涉及到硬件方面,所以主要是C/C++方面的问题。对于Java程序员来说,底层硬件都是不可见的,所以研究的意义不大。有个问题值得注意的,代码的长度,准确来说是编译后的文件(目标文件)大小,有时候跟执行效率有关。目标文件越小,占用内存空间就越小。

还有一个收获,认识了“内存对齐”。例如:在32位计算机中,一个char变量(占1个字节,即1 byte,也就是8位,8 bit)和一个long变量(占4个字节,即4 byte,也就是32位,32 bit)储存在一起。如果不进行内存对齐,要读取该long变量时,就要读取两个32位字的内容,再进行复杂的操作。但如果对齐后,读取该long变量就只要读取一个32位字的内容,没有复杂的操作,但这样就意味char变量后面紧跟着3个字节来实现对齐,就是有3个字节的内存空间浪费了。这是明显的空间换时间。同时这就知道了为什么内存容量总是32的倍数(因为32位的计算机每次处理32位数据或指令)。我估计下一代的计算机是64位(32的两倍),而不是40位、48位之类,是为了向下兼容。

PS. 可能近来睡眠不足,导致看书时精力不足(总是打瞌睡)。

睡觉前总结一下今天看书的收获。

《高质量程序设计艺术(Code Quality: The Open Source Perspective)》已经看到第3章了。本章的内容仍然很精彩!

正如书中所说,软件安全性是一个复杂又独特的难题。

1、缓冲区溢出,一个恒久的入侵课题。以前看很多黑客文章(应该是黑客故事),一开场就说溢出,但就是不知道接着做什么。书中介绍的例子是首先使得程序溢出,使得程序的指针指向要执行的恶意代码所在的内存地址,然后恶意代码便可以执行了。虽然不太懂具体的做法,但是只要想到指针能被替换,就已经很唬人了。

PS. 就算是Java/.NET,声称对缓冲区溢出漏洞是免疫的(因为它们提供了数组边界检查机制),但使用对象数组实现的环形缓冲区也有可能出现缓冲区溢出。

2、文件替换。有些软件是在root权限下运行的,并且带有更改文件权限或删除文件操作。如果把这些软件运行时所操作的文件指向一些重要的系统文件,那后果是非常严重的。

3、不可信输入。这个最简单最有名的例子是SQL注入。很多时候,特别是登陆系统时,输入的用户名都没有过滤特殊字符,或者只是在页面上用JavaScript来过滤,到了服务器就直接组装成SQL语句来查询。这时候,如果用户名后加个“;”(分号),再加个恶意的SQL语句,本来一个语句就会当作两个语句来执行(一般的数据库系统都可以识别分号为一个SQL语句的结束符),后果就不说了。

4、木马。又是恒久的主题。书中提及的不是怎么上传木马程序并运行,而是说某些开源软件的代码如果在服务器上被修改过,那用户下载来编译运行后会带来灾难。即使绝大部分的开源代码都会提供验证码(如MD5、PGP签名等)来检验是否被修改过,但绝大部分的用户都不会去检验一下。

看完本章后,突然想起以前想买的那本《入侵的艺术》,于是去“卓越”看看(http://www.amazon.cn/mn/detailApp/ref=sr_1_1?_encoding=UTF8&s=books&qid=1252254843&asin=B0011CU4RU&sr=8-1)。看过试读后,感觉这本说在写小说似的,剧情很跟《越狱(第四季)》有点像。其实最难防的是,那人直接到你机房去。

对了,还有两个细微的地方要记一下:

1)Windows 的某文件夹下,有两个可执行文件aa.com和aa.exe。如果在命令状态执行aa,那默认会先找到aa.com并执行,而找不到aa.com才会找aa.exe来执行。

2)Windows有个环境变量叫“ComSpec”,用来设置命令行解释器。

时间很快来到9月。回顾8月,唉,太浪费时间了。整个8月都不知道忙了啥,就连工作也是超无聊(每星期都有好几天没具体工作任务)。于是,希望9月来个突破!

今晚赶紧吃完饭后,独自到中大自习。本来想看《系统架构设计师教程》(想到11月去考一下),但精神不佳,于是拿出《高质量程序设计艺术(Code Quality: The Open Source Perspective)》来看。

首先第1章翻了几翻便过去了。到了第2章看到几个挺好的话题:

1)一个8位的硬件计数器是否能用来对一个256字节缓冲区的成员进行计数?
    该问题有点不明白,“硬件计数器”是什么?“一个256字节缓冲区的成员”又是什么?我觉得该提问者想说,8位的处理能力最大是255字节。纯猜测,跳过……

2)多路处理的问题
    处理多个分支的代码(如switch语句)时,作者提出以下几个处理方法:
(1)在每个分支或步骤添加注释,即具体说明;
(2)代码与复合数据成员(结构体与类)之间的关系;
(3)switch中,case的值要覆盖所有可能的情况,或者用defualt来处理可能遗漏的情况;
(4)或者根本不用多路处理,把数据与代码直接联系在一起,可以通过为原本是一个case成员的处理创建一个子类,或者是将各个实现特定接口的函数与每个数据成员相关联来实现。

3)软件发布版中的隐藏功能
    由于软件发布版中的隐藏功能,如调试功能,会带来潜在的危险与额外的资源消耗,所以应该避免。著名的反面教材是“莫里斯蠕虫”病毒,利用Unix的邮件传送代理sendmail中的调试代码,来执行命令,达到自我复制、传播的目的。

4)溢出的问题
    一个简单的表达式子:
int a = b * 100 / 255;
    当b接近int的最大值时就可能溢出,但改为这样就可以避免问题发生:
int a = b  / 255 * 100;

 经过两天的研究,终于成功用G1发彩信了。在这激动人心的时刻,首先对中国移动(特别是广东分公司)送上伟大的神兽——草泥马,以表示此刻的心情。

我的sim卡是属于广东移动的神州行畅听卡,根据androidin论坛里的教程设置APN后可以接收彩信,但发送总不成功。昨天收到一条短信,说我“使用GPRS产生CMNET流量77K,超出GPRS套餐内容,收取流量费用1.00元”。后来查了广东移动的网站(https://www.gd.chinamobile.com/easyown/operation/internet/02,52.shtml)才知道,广东移动的新GPRS套餐是CMWAP可以包月,但CMNET不能包月,且收费为1元/MB。恐怖~~于是马上把CMNET删了。

最后领悟出APN的设置,需要建立以下两个APN:

---------第一个---------
名称:cmwap
APN:cmwap
代理:10.0.0.172
端口:80
用户名:<未设置>
密码:<未设置>
服务器:<未设置>
MMSC:<未设置>
彩信代理:<未设置>
彩信端口:<未设置>
MCC:460
MNC:02
APN类型:default

---------第二个---------
名称:cmwap mms
APN:cmwap
代理:10.0.0.172
端口:80
用户名:<未设置>
密码:<未设置>
服务器:<未设置>
MMSC:http://mmsc.monternet.com
彩信代理:010.000.000.172
彩信端口:80
MCC:460
MNC:02
APN类型:mms

其中“名称”随便填,而“MNC”有的说移动的是00(零零),其实默认就可以了,我的“MNC”默认是02(零二)。以上配置没有配CMNET,所以不能上Internet。也因为广东移动的CMNET收费很变态,所以没有配CMNET。

总结一下实验结果吧。首先,虽然这个设置是没错,但是彩信发送的发送不能百分百成功。原因可能跟网络及彩信大小有关。彩信大小为1K,成功率较高,但白天在公司,彩信一条都发不出去。晚上发的话,成功率很高,发了几条,别人都能收到,我也给自己发了个照片,40K左右,发送和接收都很顺利。

PS. 人家玩G1都上3G(外国的),而我还在研究2.5G的使用……正如应老板说的:“脑残,就玩别人不玩的东西”。

今天下班后到超市买菜,付钱时,收银机“档机”了。那超市经理不断地打电话,从其对话中听到貌似是断了网络而引起的。就在等待付钱的时候,看着他们一堆人在乱搞。

说说那收银机吧。一开始以为它只是由一个显示器、键盘和钱柜(就是可以自动弹出来的那个小铁盒)组成。但是看到收银员拔网线时,居然从柜子底下抽出个电脑主机,那我就明白了--这就是一台完整个的电脑,只是多了钱柜这个外设。

然后看到收银员在操作时,退出了那个收钱软件,屏幕显示熟悉的Windows界面(应该是640×480的分辨率)。从图标来看应该是Windows 2000或者Windows ME。那整个收银机系统就明显是个古老的C/S解决方案,而且是基于Windows平台的。

该解决方案的优点是成熟稳定,还有价格便宜(古老的机器、盗版的软件)。一想到这,我就鄙视那它了。但是它有个功能我没有注意到,就是:由于基于C/S,所以客户端可以先在本地保存交易记录,然后手动上传到服务器。该功能的应用场合就是像现在,网络故障,或者服务器出了问题的时候,仍然可以记录交易,确保超市的交易不受影响。

其实技术和设备主要是为了满足应用而存在的,而在应用中只要找到满足需求的解决方案就可以了。就像我的表姐夫那样,配了台四核电脑,加上SLi双显卡,还有Apple键盘、24寸16:9宽屏液晶……但我经常看到他只是拿着台上网本来上网。

这几天看到网上的报道说,国产的“龙芯”CPU终于获得MIPS公司的授权,可以贴上“MIPS-compatible”标签,还支持Android操作系统。据说这授权费大约500万美圆左右(由此估计Intel公司的x86架构授权费会是个天价)。网上对这事情的评价褒贬不一。其中,有批评的言论居然说“CPU核自主产权战略失败”!

我觉得,从前景来说,是好事。首先,支持MIPS架构,就有了Linux操作系统的支持(这包括我天天在用的Android),然后就拥有了一大堆开源软件可用了。虽然说MIPS架构是别人的东西(主要是指令集系统),但毕竟“龙芯”是中国人自己研发的,(根据资料来看)就像是基于C语言标准的编译器的不同实现一样。如果“龙芯”是完全自己做的指令集,那操作系统要自己研发,驱动、应用软件等一大堆东西也要自己去做。这样不仅给自己添麻烦,还与世界脱节。最重要的是推广起来将会十分艰难(现在Linux难推广,其中最大的原因也是软件不足)。至于为什么是MPS,而不是x86、ARM、PowerPC或其它,别人已经说得很清楚了。相关的详细说明如下:(来自龙芯官方论坛)

胡伟武关于计算所购买MIPS结构授权的几点说明
http://www.lemote.com/bbs/viewthread.php?tid=23935&extra=page%3D1

 关于龙芯拿MIPS授权的再一点理解
http://www.lemote.com/bbs/viewthread.php?tid=23886&extra=page%3D2

今年年头看到“龙芯”产品化后(上网本和迷你主机),看到其功耗非常低,于是想买个来做“二奶机”,主要是挂P2P和做移动存储。但售价还是比预想的高,加上购买不方便,而且同一价位可考虑的有ATOM和Nano这两个x86的CPU。后来没心思想这事情,那“二奶机”的想法便不了了之。

最后,希望胡伟武教授能够继续努力!

PS. 近来工信部出了个“绿坝”河蟹软件,据说花了纳税人3000万人民币。这软件的评价嘛,大家有目共睹,而且还无视别人开源软件的许可证……唉,让我无奈得无话可说……

这个星期五(2009-06-12),部门组织了一次WebService的学习。花了将近3个小时的培训中,竟不知其所云,只好用G1上网查资料。一看人家的资料,立马就把HTTP、SOAP、WSDL、UDDI等技术或标准理解清楚了。

首先是WebService,它是一种面向服务的架构的技术,通过标准的Web协议提供服务,目的是保证不同平台的应用服务可以互操作(摘自http://zh.wikipedia.org/wiki/Web%E6%9C%8D%E5%8A%A1)。最简单的理解是提供XML数据的Web服务,其XML数据是基于WSDL标准的。

接着是UDDI,找到不错的文章《理解UDDI》,原文地址:http://www.ibm.com/developerworks/cn/webservices/ws-featuddi/

该文章有个很清晰的图,解释了这几个东西的关系,如下:

[caption id="" align="aligncenter" width="424" caption="UDDI 的分层 Web 服务协议栈"]UDDI 的分层 Web 服务协议栈[/caption]

然后是SOAP,即简单对象访问协议,全写为Simple Object Access Protocol。它是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息(摘自http://www.w3school.com.cn/soap/)。最权威的说明,参看http://www.w3.org/TR/soap/。我的理解是,SOAP利用XML来封装数据,再利用HTTP协议封装后进行传输。

WSDL就更好解释了,就是个XML,只是格式标准化了。这样,服务提供方(服务端)只要按照WSDL的标准封装数据,接收方(客户端)就可以读取。但是,好象不同WSDL实现存在一些细微的差别。培训中,曾爆发了对WSDL的内容的争论,我是在争论变成争吵时才发现的,所以不知道具体吵什么。

其实这几个东西就是SOA所需的技术。唉~~已经是很老的东西了。

今晚很热,也很无聊,所以到外面逛逛——首选的地方是房子附近的中大。无它的,只是对当代大学生的夜生活有点兴趣,并怀念一下当年夜闯战场看野合的经历。但是,没什么收获,只是看到一些穿着暴露的MM,行色匆匆地往校外跑……

还是说点正经的吧。在校内的路上,偶然看到手机有WiFi信号的提示,有点惊讶!(但是再想想,宿舍里装个无线网络也不奇怪吧?)于是产生了一个想法——去寻找可用的WiFi!这样以后就可以在校园里上上网、吹吹风,顺便看看MM……

中大里逛了一圈,发现“动感地带”的营业厅(类似那种校园里交话费的地方)那里找到无加密的WiFi,附近还有一对情侣拿着笔记本上QQ。可是连上去就发现,网关加密了(要输入用户名跟密码才可以上外网)。登陆页面上除了英文就是问号,估计是编码不被支持。幸好有个咨询电话,打过一问才知道只是个搞网络维护的(技术支持),对帐号怎么申请一无所知,他推荐我打10086。于是又咨询10086的人工服务,那MM最后的答复是,中国移动没提供无线上网服务,这边的3G网络也没开通,让我打10000号咨询一下中国电信,顿时晕倒~~~没办法,只好等明天到那营业厅咨询一下。

然后又到了附近的商业区,看看有没有地方有免费WiFi,又可以坐下来喝东西的地方。又逛了一圈,发现很多WiFi信号,应该是附近的公司和住宅的,但不是信号弱就是加了密。最后找到了两个:一个是在一栋大厦前发现的,估计是那公司内部的WiFi,但由于附近阴暗,感觉不安全,于是测试过能连上就跑了(不知道能不能再作进一步行动,比如进入那公司的内部网之类)。另一个是一家酒店的CoffeeShop(咖啡馆),平时走过都不知道这酒店还有个CoffeeShop!居然跟踪WiFi信号找到这家店,但是进去前要经过酒店大堂,而且不知道里面的消费如何,还是没进去。

经过今晚的行动,深深感受到WiFi已经溶入我们的生活,变成很平凡的东西了。同时证明我买G1的选择是正确的!拿着它,比MID、上网本等都要好(轻便、实用,想象一下拿着笔记本在街上找WiFi就知道了)。

PS. 1、生活中的无线信号非常多——电视信号、GPS、手机信号、FM调频、WiFi等,究竟这些无线信号除了方便我们的生活以外,对我们的健康有没有带来什么影响呢?如果我们的生命受到这些东西的危害,又应该怎么去维护自己的权益,或者找谁去赔偿我们的损失呢?答案还是Who Knows。

2、渐渐地,G1已经溶入到我的生活了。例如:见到有趣的事物就用G1拍下来,到CoffeeShop就用G1来上网,在车上就用G1来看书、听歌、看电影,做饭、洗碗、洗澡都用G1来放歌(音质很一般,没有低音,带上原配的耳机也一样),甚至上厕所也带着G1。这东西完全替代了那老迈的e310之余,还带来很多新乐趣。是时候复习一下Linux命令了。

3、晚上十一、二点一个人在大街上找WiFi,Crazy~!这就足够证明我有多无聊了……

2009-06-07补充:中大的那个WiFi没戏了,那负责人说该WiFi主要是建给自己用的,如果别人用的话收费很贵,要两毛一分钟。明显是说,我这个WiFi你就别想了。

还没买G1之前就看到网上有人说可以在G1上跑Debian。那时就想,能运行Debian,G1不就万能了吗?今天通过实践,证明了我的想法是正确的。

其实几天前就把Debian装到G1上了,也用apt-get来安装而了nginx。昨晚把nginx(一个俄罗斯的HTTP服务器,以小巧、占用资源少、高并发等优点著称)重新以编译源码方式安装,然后把它的HTML文件夹挂到SD卡上,以便把SD卡上的一些HTML文档挂上去。最终的目的是实现本地HTTP服务,并用系统自带的浏览器(Chrome Lite)来看HTML文档(由于Chrome Lite不支持查看本地文件系统中的HTML文档,而用HTML Viewer又没Chrome Lite那么强大)。虽然这做法非常Crazy,但实现后很有满足感。今天把G1连到公司的WiFi,然后用台式机访问其HTTP服务,感觉很炫。同事们看了,也十分惊讶。

后来萌生了个想法。由于G1上不能无线传送文件,那可不可以绕个圈子来实现呢?首先装个aNetShare,该软件可以使G1变成无线AP(同类的软件还有WiFi Tether)。这样其它机器就可以通过WiFi连我的G1,然后我只要提供个HTTP服务或者FTP服务,那就可以共享我的文件,别人就可以下载了。呃,好像好麻烦……不过挺好玩的。明天再借个笔记本试试,看我的想法可不可以实现。

近来就忙着玩G1,还比较认真地开始去看C语言,以致很多事情都来不及做了,希望这个周末能赶赶进度。

PS. 1.看着程序在G1上慢慢编译,是一种很写意的感觉,但编译过程中出现error的情况除外。

2.看了C语言,才知道,原来两个数交换可以不用再建个临时变量的,用“异或”就可以了。感觉很神奇,而且节省时间跟空间。例如:
一般做法是这样:
int a=111;
int b=222;
int tmp=0;
tmp=a;
a=b;
b=tmp;

用“异或”实现:
int a=111;
int b=222;
a=a^b;
b=a^b;
a=a^b;