08 2007存档

“冤家”

| | Comments (0) | TrackBacks (0)
        我一直奇怪为什么T-62坦克之后短短几年苏联就又研发了T-64,而T-90号称是“T-72大改”,为什么不是从T-80改过来呢?昨天看了篇文章才明白为什么。
       苏联的坦克设计和制造由两大集团负责:鄂木斯克集团和下塔吉尔集团,创始人分别为科京和柯什金。这两人来头都不小,科京是KV系列坦克,斯大林重型系列坦克的设计者,而柯什金则是大名鼎鼎的“英雄坦克”T-34的设计者,两人都为苏联的坦克事业乃至军事工业立下了汗马功劳。

IS-2
IS-2重型坦克


T-34
T-34坦克

        早就听说科京是“贵族出身”,想想吧,拿当时最高领导人的名字来命名自己设计的重型坦克,没点背景是不行的,果不其然——科京的岳父就是苏联老资格元帅伏罗希洛夫——斯大林身边的“大红人”。相比之下,柯什金就显得出生贫寒了,他是从普通技术工人一步一步做到总设计师的。就这一点,我更欣赏柯什金,虽然从照片看他没有科京帅....

科京        柯什金
科京
   
柯什金

       如果说二战时斯大林重型坦克和T-34使两大制造集团平分秋色的话,二战后,下塔吉尔集团的设计能力则一直领先于鄂木斯克。T-55,T-62,T-72以及T-90,这些响亮的坦克型号都出自下塔吉尔。而鄂木斯克的IS-8(斯大林死后改称T-10——这就是苏联的政治)、T-64都是中看不中用,T-10又大又笨极难使用,T-64在阿富汗战场也是故障频出,让苏联的后勤部门大为头痛。而后来的T-80也是叫好不叫座。
       这就是为什么T-62之后会有T-64,因为鄂木斯克不满下塔吉尔的成功,要求研发新产品。而T-90只能是从T-72改进而来,总不能去拿别人的T-80来改吧...
       “同行是冤家”,这两大集团就这么你追我赶的过了八十多年。但我还是很乐意看到两个充满活力的设计公司为了追求更完美的产品而不断竞争,这才能造出一流的武器!

        05年5月初的时候Intel中国到软件学院来招实习生,发了一份相关文档介绍实习职位及要求,我看了激动得不得了——里面有开发编译器甚至嵌入式操作系统的实习职位!在中国,很多程序员一辈子就是通过写一些高度重复的脚本代码来谋生而已,能够做编译器、操作系统简直是做梦都不敢想的事,现在竟然有实习的机会,真是太难得了!估计招聘一定超级严格,所以我紧急借了很多操作系统内核以及Intel芯片知识方面的书来“加强”一下。
        到了5月中旬,大批软件学院学生(当然包括我)前往国贸的嘉里中心(Intel中国北京总部)面试,面试出乎意料的简单,只是关于C语言的简单知识和一些小技巧,通告我们说可能在北京实习但也有可能调往上海,上海方面也会电话面试。大约一周后上海方面打电话来了,也只是问了设计模式和几个数学问题。
       大约5月底就通知我面试通过可以到Intel中国实习了,但工作内容是做黑盒测试。问了周围应聘上的同学,也都是被发配黑盒测试的工作。工资是1500元一个月,如果在上海实习,补贴250元——1750一个月,看这工资就知道肯定不是开发操作系统或者编译器的。
       真是岂有此理!你Intel如果只有黑盒测试的实习职位,就请写明白!为什么写的那么漂亮,做的又是另一套!当时我是非常失望,家里却一直劝我说能到著名外企实习机会难得尽量还是去试试,但我早已不是高中时代那个样子,说什么都不会勉强自己,最后直接拒了Intel。
       后来6月份选择去Intel实习的同学出发了,干了一两个月后抱怨连篇:都是些无聊简单的黑盒测试工作,招个民工都能做,之所以招软件学院的学生,是因为反正都是1500元一个月!很多同学受不了想走,Intel说走可以,但名字就要上黑名单,以后你就再不能应聘Intel公司的工作。这哪他妈是外企公司啊,简直是变相的IT奴隶贩子!
       后来才了解到,Intel中国压根就不做任何核心技术,只是做Intel美国的测试外包而已,所以什么开发编译器开发操作系统全都是幌子,他是用这个先把“仰慕Intel大名”的实习生们搞过去,然后寄希望于实习生“接受现状”,最后“嫁鸡随鸡,嫁狗随狗”在Intel中国当满一年的廉价劳动力。
       Intel中国给计算机系的实习生是4、5千一个月工资,给软件学院实习生就是1500元!不过也不能怪别人歧视——谁叫自己考研没赶上计算机系的分数线呢?还多掏了4万元学费!

       到了6月份IBM中国也开始招聘实习生,先是网上提交简历,完了他又觉得不过瘾,又叫实习生们自己拿着简历跑到北京北边的上地开发区创新大厦去面试,五六百人在炎热的六月艳阳天挤在创新大厦的门口,巴巴的等着叫号进去,那是什么场景?!很多人等了一个早上,进去第一面就被拒了,那是什么心情?!谁叫人家IBM有钱有势呢,就把你一群实习生当要饭的耍怎么了!
       记得那天我还进了二面,但即使是二面也只是问你用过什么开源软件,用过什么软件工程工具,用过IBM的软件没有这类问题。很多同学像我一样6点起床,8点开始在门口挤,下午2点进入二面,饿着肚子啥都没吃,就是为了听他们问这些废话。
       至于那次IBM到底招了多少人就没人知道了。后来才知道:IBM中国招实习也没有开发职位...下面就不用说了,猜也能猜到怎么回事了。IBM搞这么大声势招实习生其实是为了品牌宣传,他看简历就看有没有用过DB2、WebShpere等产品,如果没有,你再多本事再多经验他也不理你,他就希望招实习生只用IBM的产品,以后实习完了去到其它地方就能帮他宣传IBM的东西了,真是想得周到。
      
        7月份SUN中国给的实习职位更离谱,连测试都不是:所有测试用例都写好了,等着我去给他跑起来呢!

       9月份我去现在工作的公司面试开发职位,面试官是后来的上司,难得遇到兴趣这么一致的面试官,大家聊得很高兴,尽管二面的时候公司的技术总监觉得我”太强势,可能以后跟同事合作有困难“,最后还是应聘上了。感谢面试官,我有了第一个正式的工作机会。

        到了10月份几个同学聚,才知道去Intel的人大部分都受不了回来了,另外找了实习,好歹工资过得去,能养活自己。极少部分同学继续留在Intel,期望毕业后转正拿上“人拿的工资”。
        再后来07年Intel裁员,很多转正的同学才拿了一两个月的正式工资就被裁掉了...幸好我没有迷信外企公司的牌子,跑到Intel去,不然早被他玩死了。

 
====== 2010.6.17 ======
我思考了这么多年也想不明白为什么这些外企招实习生那么离谱,可能这才是原因吧。

昆汀作品

| | Comments (0) | TrackBacks (0)
中午看了电影《杀出个黎明》,典型的“昆汀”风格——又诡异又暴力,还充满了黑色幽默,和《杀死比尔》类似。
主演是“蝙蝠侠”乔治.克鲁尼和导演本人——昆汀.塔伦蒂诺。你别说,昆汀演变态真是像极了,完全不用化妆,角色的风格和他本人的风格完全一致,八成这个角色就是他自己添进来的....

经典对白:

(绑匪拿枪押送人质)

人质: 你....你要带我们去哪里?

绑匪: (面无表情)墨西哥

人质: 墨西哥....那里、那里能有什么呢?...

绑匪: (还是面无表情)墨西哥人

我原以为图-95的同轴对转螺旋桨是为了省油(也不知道是哪部记录片这么说的,还是我记错了?),而且对转螺旋桨是门“高级技术”。我错了,对转螺旋桨是门老技术,而且它也不是为了省油。
当螺旋桨转动时,比如顺时针转动时,根据反作用力原理,它自然会对发动机产生一个逆时针方向的力(扭矩),这个力会造成发动机逆时针转动,同时也就使飞机逆时针侧翻。对于单发(单发动机)螺旋桨飞机(二战的很多战斗机都是)来说,这种力尤其明显,工程师通常是通过调节副翼来“配平”这种翻转力的。


副翼的位置


也就是让飞机左右副翼俯仰角不同,产生一个克服翻转的力,最终使飞机保持水平。但这个翻转力的大小是随着飞行速度、飞行方向甚至风向的变化而变化的,所以副翼必须跟着调节,这就加大了副翼设计的技术难度。要绕开这个麻烦,就是用对转螺旋桨技术:两个同轴螺旋桨紧靠着,反方向转动,扭矩相互抵消,飞机就不会受到侧翻的力。当然,两个螺旋桨的桨叶扭转方向是不同的,这样两个对转的螺旋桨产生的才都是向同一个方向的推力。
二战后的很多大型螺旋桨飞机都采用了这一技术,因为对于大型飞机来说,对转螺旋桨所带来的平衡性尤其重要。苏联的安-22运输机、图-95轰炸机就是典型的例子。


安-22运输机



图-95的对转螺旋桨


对于直升机来说,也有同样的问题,所以直升机尾部都有一个小螺旋桨用于平衡。但也有直升机采用对转螺旋桨,省掉了尾巴上的那个小螺旋桨,稳定性更好,比如俄罗斯的卡-50(“黑鲨”)武装直升机。俄国人似乎很偏爱对转螺旋桨技术。


卡-50


还有潜艇、鱼雷,也有使用对转螺旋桨做为推进器的,都是为了更高的稳定性。

做项目时我需要序列化STL的map,当然,map本身没有这个功能,我只能自己写。必须写这么各类:能方便的序列化各种map,比如 map<string,sizet>、map< string,vector<sizet> >。我首先想到的是模板特化:

template<class T>
class ContainerSerial
{
};

typedef map<string,size_t> StringSizeMap;

template<>
class ContainerSerial<StringSizeMap>
{
public:
    ContainerSerial(StringSizeMap& m):m_container(m){}

    //对应StringSizeMap的实现
    save(){...}
    load(){...}

private:
   StringSizeMap& m_container;

};

typedef map< string,vector<size_t> > StringVecSizeMap;

template<>
class ContainerSerial<StringVecSizeMap>
{
public:

    ContainerSerial(StringVecSizeMap& m):m_container(m){}

    //对应StringVecSizeMap的实现
    save(){...}
    load(){...}

private:
   StringVecSizeMap& m_container;

};
这样在使用时就可以挑选想要使用的ContainerSerial:

StringSizeMap myMap;
ContainerSerail<StringSizeMap> serialer(myMap);
serialer.save();
serialer.load();
 
这个实现有几个问题:
1
.   ContainerSerial的生命周期依赖于StringSizeMap,看以上代码,如果myMap析构了,serialer却还在那里save、 load,肯定是core dump.在c++中,对象的生命周期管理是很费精力的事,所以要避免两个对象产生生命期依赖。

2.   由于是模板,整个实现代码都放在一个ContainerSerial.h文件里,其它cpp文件来include它,于是各个类对应的object文件都带有ContainerSerial的实现,最后链接时造成"function xxx redefined"...这个问题虽然可以绕开,但使用模板特化毕竟是比较复杂的事情,它的引入难免对源代码结构产生冲击。

其实干嘛想这么复杂呢?用c++的函数重载就可以做到了!

//ContainerSerial.h:

saveContainer(StringSizeMap& m);
loadContainer(StringSizeMap& m);

saveContainer(StringVecSizeMap& m);
loadContainer(StringVecSizeMap& m);

//ContainerSerial.cpp:

saveContainer(StringSizeMap& m)
{...}

loadContainer(StringSizeMap& m)
{...}

saveContainer(StringVecSizeMap& m)
{...}

loadContainer(StringVecSizeMap& m)
{...}

可以用PBreak到youtube等使用flv格式的视频网站上方便的下载视频。
试过很多号称能下载视频的插件,只有这个能用 :)

1. 下载安装
2. 进入youtube的页面,选择你喜欢的视频网页
3. 此时firefox右下角会有一个斜箭头,点击即可下载视频!

插件地址: https://addons.mozilla.org/en-US/firefox/addon/4252

军博之行

| | Comments (0) | TrackBacks (0)
上周四和老爸一起去了一趟军博。我到北京八年了,这是第一次去军博,就是奔着建军80周年展览去的。
可惜数码相机是借的,模式没有调对,所以图像都雾蒙蒙的...可惜啊

99式主战坦克


99式的炮塔


99式的履带、驱动轮、负重轮近拍


155毫米自行榴弹炮


长得很像俄罗斯的BMP-2战车


导弹车


"飞豹"歼击轰炸机


防空系统

图-95复出

| | Comments (0) | TrackBacks (0)
昨天看晚间新闻听到俄罗斯又开始了中断近15年的战略轰炸机巡逻任务,老毛子把自己“珍藏”了多年的图-95(熊)、图-22(逆火),和目前还算得上先进的图-160(海盗旗)都搬了出来。面对这几年来的北约东扩和最近几个月美国咄咄逼人的“战略导弹防御计划”,俄国熊不得不低吼两声了。
图-95是前苏联图波列夫飞机设计局为苏联空军研制的远程战略轰炸机。1951年开始研制,1954年第一架原型机首次试飞,批生产型于1956年开始交付使用。早期型共生产了300多架,除用作战略轰炸机之外,还被用来执行电子侦察、照相侦察、海上巡逻反潜和通信中继等任务。 80年代中期,图95轰炸机又开始恢复生产,主要生产可带巡航导弹的图-95MS轰炸机和由图95改型的海上侦察/反潜机图-142M3型。1992 年停止生产。现在约有150架图-95M/K/MS仍在服役。此次执行巡逻任务的就是图-95MS。
当年图-95刚研制出来,苏联人就开着它到阅兵式上给西方国家“秀”了一把——红色帝国拥有了能带着核武器一口气飞到美国的战略轰炸机!1961年10月苏联进行历史上最大规模的核实验便是用图-95空投一颗氢弹,可见“熊”在苏联军事力量中的地位。图-95至今已经服役了50多年,其漫长的服役时间恐怕只有美国的B-52可与之比肩。
不过普京的这一次举动我感觉还是比较持重,比较轻微的,想想看:毕竟图-95是一种老式飞机,其对转螺旋桨技术虽然新颖,但在超音速喷气式飞机称霸的今天,仍显得力不从心,它不可能真的突破美国的防空网,普京这次搬出它,更多的是在引用它的象征含义——俄罗斯依然拥有苏联时代不可一世的战略威慑力量!
新闻还说美军战斗机紧急起飞“护送”图-95,双方飞行员“相视而笑”。遥想美苏争霸之时,十几年间,图-95一巡逻,美战斗机就紧紧跟上,大家“比翼双飞”,虽为敌人,却也有几分惺惺相惜之感。如今历史重演,飞行员怎能不会心一笑?
今天下午买了份《参考消息》,也是报的这个新闻,正面还有图95的巡航照片。看着图-95瘦削而威武的身影,想起他当初威震四方,如今老骥伏枥、重卫尊严,忍不住感叹:
老兵,辛苦了!



图-95起飞重量185吨,巡航时速760公里,最大航程14000公里。
tu-95
图-95


图-160是由图波列夫设计局于70 年代开始设计的变后掠翼重型超音速战略轰炸机,估计该机是在70年代初图-22M首次试飞后开始研制的。图-160的研制是采用招标的方式进行的,参与招标的有图波列夫设计局、米亚设计局和苏霍伊设计局。考虑到图波列夫设计局具有大型轰炸机的设计经验和生产能力,所以最后决定还让图波列夫设计局在M-18方案的基础上研制图-160战略轰炸机,批量生产厂家为喀山飞机制造厂。原型机81年12月19日首飞,87年5月开始进入部队服役,88年形成作战能力,替代米亚-4和图-95飞机执行战略任务。据信至92年时生产40架以后暂时停产。
图-160起飞重量268吨,最大时速2000公里,最大航程12300公里。

tu-160
图-160


图-22M“逆火”(Backfire)是苏联图波列夫设计局在图-22“眼罩” (Blinder)基础上进行了极大的改进设计出的超音速变后掠翼中型战略轰炸机,图-22M既可以进行战略核轰炸,又可以进行战术轰炸--尤其是携带大威力反舰导弹,远距离快速奔袭,攻击美国航空母舰编队。因此图-22M曾经是美苏之间裁军谈判的主要焦点之一,目前图-22M3是俄罗斯战略轰炸及反舰艇作战核心组成部分之一。图-22M的研制要从图-22讲起。1959年美国第一代超音速轰炸机B-58批量生产,并投入使用。1961年苏联第一种超音速轰炸机图-22在莫斯科航空节露面,随后装备部队,仅比美国晚两三年。图波列夫没计局于1955中开始设计图-22,58年首次试飞。
图-22起飞重量279吨,最大时速2000公里,最大航程12000公里。

tu-22
图-22


阿·图波列夫的父亲安德烈·图波列夫是苏联最著名的飞机设计师,也是俄罗斯飞机制造业的奠基人之一,图波列夫父子被俄罗斯人称为“伟大的父亲和伟大的儿子”。父子二人都工作于俄罗斯图波列夫设计局。

      
安.图波列夫
   
阿.图波列夫

T-72坦克

| | Comments (0) | TrackBacks (0)
苏联60年代研制的T-64主战坦克存在种种问题不能大量生产,无法完全替换数量众多的T-54/55坦克。为了保持坦 克技术和数量的优势,苏联利用T-64坦克的某些技术,经T-70试验车,发展成T-72主战坦克,1971年开始服役。 T-72坦克不但有效取代了T-54/55,更弥补了T-64和T-80之类高性能坦克数量的不足,使苏联装甲部队维持了一定的数量优势。
1973年下塔吉尔的T-62生产线改生产T-72,1974年批量装备部队。T-72系列坦克产量在20000辆以上,捷克、波兰、印度、南斯拉夫和罗马尼亚也有生产。目前至少有15个国家装备了T-72系列。


比起T-62和T-55,T-72都要显得“现代”的多,它采用了更矮的类似于圆盘状的焊接炮塔(我估计T-55/T-62的炮塔都是铸造的),6个负重轮。整个70年代,T-72几乎是苏联装甲力量的象征,直到现在T-72依然是俄罗斯陆军的主力坦克。


T-55坦克

| | Comments (0) | TrackBacks (0)
T-54、55 坦克是前苏联研制的第一代主战坦克,1947 年开始研制,1950 年定型投产,是苏联五十年代的装备车型。其主要改进型为 T-54A 、T-54Б和T-54C,T-54C 的改进型称 T-55 。T-54 坦克是世界上数量最多的坦克,从 1948 - 1963 年,制造了 30000 辆。
我简直没有办法区分T-55和T-62,它们都是圆形炮塔、5个负重轮,外观基本一致。



这是T-55参加阅兵的录像,你能看出它和T-62有什么差别吗?...



T-62坦克是苏联继T-54/T-55坦克之后于50年代末发展的一代新型主战坦克,1962年定型,1964年成批生产并装备部队,1965年5月首次出现在红场阅兵行列中。
苏联T-62坦克的生产一直持续到70年代末T-72坦克投产时为止,共计生产约2万辆。为满足军火市场的大量需求,苏联还准许捷史斯洛伐克生产该坦克, 在1973~1978年间大约生产了1500辆。朝鲜民主主义义人民共和国也在为本国和出口市场生产T-62坦克。

该坦克大量用于1973年中东战争,并参加了苏联入侵阿富汗的行动,而珍宝岛事件里中苏苦苦争夺的那辆停在河中央的坦克就是T-62。
影片中T-62一路气势汹汹,摧枯拉朽,并配以重金属摇滚乐,非常动感,非常威风。


操作数量较大的文件:
billing1.edu.cnb /home/y/var/p4p% find clickrec -name "BILL???200507*" > c07.lst

billing1.edu.cnb /home/y/var/p4p% tar -T c07.lst -czf clickrec.200507.tar.gz

billing1.edu.cnb /home/y/var/p4p% cat c07.lst | xargs rm
Boost.assignment库的使用及简单分析

相信大多数使用STL的人都是为了使用里面的容器,使用vector、list、map的程序员对以下代码可以说是非常熟悉了:

vector i_v;

i_v.push_back(1);

i_v.push_back(2);

i_v.push_back(3);

i_v.push_back(4);

i_v.push_back(5);
挺枯燥,是吧?用boost的assignment库可以让这一过程简洁得多:


#include "boost/assign/std/vector.hpp"

using namespace
boost::assign;

vector i_v;

i_v += 1,2,3,4,5;
效果与上面的程序一致,可读性却好很多,看上去有点“脚本语言”的感觉了。 对于关联容器,也有类似的便洁方法:

#include "boost/assign/list_inserter.hpp"

#include "string"

using namespace
std;

using namespace
boost::assign;map months;

insert( months )

(
"january", 31 )( "february", 28 )

(
"march", 31 )( "april", 30 )

(
"may", 31 )( "june", 30 )

(
"july", 31 )( "august", 31 )

(
"september", 30 )( "october", 31 )

(
"november", 30 )( "december", 31 );

分析assignment的源代码,先看 assign
/std/vector.hpp:

template
< class V, class A, class V2 >

inline
list_inserter< assign_detail::call_push_back< std::vector >, V >

operator
+=( std::vector & c, V2 v )

{


return
push_back( c )( v );

}


//assign/List_inserter.hpp:


template
< class C >

inline
list_inserter< assign_detail::call_push_back ,

BOOST_DEDUCED_TYPENAME C::value_type >

push_back( C& c )

{


static
BOOST_DEDUCED_TYPENAME C::value_type* p = 0;

return
make_list_inserter( assign_detail::call_push_back ( c ), p );

}


template
< class Function, class Argument >

inline
list_inserter

make_list_inserter( Function fun, Argument* )

{


return
list_inserter ( fun );

}


重载了+=操作符,所以才有 i_v+=1,2,3,4,5 这种写法。可以看出 push_back函数返回一个list_inserter,对应例子,push_back(c)(v)即为push_back(i_v)(1),返回一个仿函数list_inserter <:call_push_back ="">>, int>(assign_detail::call_push_back(i_v))(1) 。 那数字间的逗号又是怎么处理的呢?不知道大家还记不记得 std::cout<< 1 << 2 << 3; 此处的<<和assign中的逗号其实是一个道理,<<操作符返回一个iostream,而逗号操作符返回一个 list_inserter (+=操作符返回第一个list_inserter,其它的逗号“跟进”):

template
< class Function, class Argument = assign_detail::forward_n_arguments >

class
list_inserter

{


list_inserter( Function fun ) : insert_( fun )

{}

....


template
< class T >

list_inserter& operator,( const T& r )

{


insert_( r );

return
*this;

}



private
: Function insert_;

}
这里的insert_就是先前的assign_detail::call_push_back ( c ),所以insert_( r )就是assign_detail::call_push_back ( c )( r ), 看看
:

template
< class C >

class
call_push_back

{


C& c_; public: call_push_back( C& c ) : c_( c )

{ }


template
< class T > void operator()( T r )

{


c_.push_back( r );

}

};
实际是调用了c.push_back(r),对应到上面的例子,也就是调用了 i_v.push_back(1) 。 至于map的insert,实现与此类似。
Python , Delphi , Loki 三个单词有趣的来源

许多程序设计语言和开发工具以及库的名字都来源与神话,颇有意思:

     阿波罗是同时出现在希腊和罗马神话中的奥林帕斯十二大神之一。他除了拥有太阳神的身分,同时还有预言、艺术、医术之神的称号。阿波罗是宙斯和乐朵的儿子,和阿蒂蜜斯是双胞胎兄妹。

  阿波罗出生几天后便长大成人。为了寻找预言的圣地,他特地前往德尔斐(Delphi)。路途中,他先到达哈利亚多斯,原本打算将宁芙仙子泰尔普沙(Thelpusa)所在的水泉──一个拥有预言能力的水泉──立为圣地,但是泰尔普沙推荐,德尔斐应该更适合阿波罗。事实上泰尔普沙是不希望自己的圣地被夺走,明明知道德尔斐是一只拥有预言能力的母巨蟒毕颂(Python)的地盘,还故意让阿波罗到德尔斐去。

当然python语言的开发者是喜欢一个叫python的马戏团才给自己的脚本语言起名的,但Python这个单词的出处应该是在此。

至于c++中的Loki库:

      Loki为北欧神话中的火神,也是邪恶与灾难之神。虽为巨人族之子却有着与北欧众神一样的神族地位,但最终与诸神对立并引发了最终战争Ragnarok——诸神之黄昏。
1. 用LWP::Simple中的get下了一个HTML,用模式匹配解析url,可气的是明明看见了某个url,用模式匹配却匹配不到,考虑到html中有换行,所以我用了参数/s以 将多行折起来,但是依然无效。后来发现必须用 s/[ s]//g 把其中的stopword全去掉才行。因为模式匹配遇到这些符号会中断。

2. 著名的Text::Iconv可以把UTF-8转为GBK( 路人皆知了:) ),但html中有很多符号会打断这一转码过程,结果输出的是空。应该用 new Convert("utf-8", "gbk//ignore) 创建convert,这样即使发现了不能顺利转换某个字符,也能跳过它继续处理其它字符,避免输出为空。

开发中遇到问题:一个用xml格式写的后缀名为.mod的文件,用vim打开它没有语法颜色,输入命令 set filetype=xml 可以了,但不可能每次打开它都输这么一句,所以修改~/.vimrc,加入以下几句:

if has("autocmd")

       autocmd BufNewFile,Bufread *.mod set syntax=xml

endif

以后每次打开后缀为.mod的文件,vim就以xml语法颜色处理。

        今天打开Gmail,居然收到一封英文的求职信,署名Andrej。信中人自述有很多年的c++开发经验,还列出了好几个自己开发的项目相关的网址。看到信的结尾我才明 白,这封信是发给 comp.lang.c++ 新闻组所有人的。这位老兄找工作都找到新闻组来了,唉....大概是手头紧吧。
        大家都是程序员,而且都是c++ fans,看到对方这么“落魄”,心里总不是滋味。以前找不到工作或是找到工作待遇很低的时候,常常想:坚持一阵子,积累积累经验,以后待遇会高起来的。 现在看来未必如此,比如现在,我天天写模板,难道我不想写代码吗?但是代码被老员工(我没有怪他们的意思)写完了,我被勒令使用那些代码而已——很无聊 吧。这种活根本谈不上什么经验积累,只有一离开公司,这些东西马上就分文不值。其实不光是写模板,就算是写代码的人,也常常是在某一方面常年累月的干,万 一被公司抛弃一点办法都没有。记得03年联想裁员的时候,有些老员工掉眼泪,人家不是伤感,是发觉自己一离开公司就没有可去之处了。
        我现在是想通了,干工作不能光靠熟练,还得学习领域方面的知识,没事儿不要盲目加班,有空多学习学习新东西,也为将来打算。靠公司是不安全的,还是得靠自己。
        祝福Andrej,但愿他找到一份好工作。

利用setjmp和longjmp处理异常

      c语言种可以利用setjmp和longjmp来实现程序的直接跳转,这种机制并不适用于在程序开发中设计逻辑流程,但用来实现异常处理机制则是非常的适用。

      比如写一个实现内存分配的函数,可以这样:

void *allocate(unsigned n)
{
 void *new=malloc();

 if (new)
  return new;

 if (Allocation_handled)    //如果new为NULL,则执行到此判断
  longjmp(Allocate_Failed,1); //跳转

 assert(0);
}

      而在调用时,可以先设好跳转的“目的地”,再调用allocate:

char *buf;
Allocation_handled=1;

if ( setjmp(Allocate_Failed) )
{
 fprintf(stderr,"Couldn't allocate the buffer! ");
 exit(1);
}

buf = allocate(1000000);

Allocation_handled=0

      为了使用方便可以把以上setjmp和longjmp做一个宏定义,这里就不细说了。但总的来说这个异常处理机制是不如c++的那么方便,但对于c语言来说也算不错了。

对话节选 昨天看了《斯巴达三百壮士》(The 300 spartas),1962年的老电影,讲的是古希腊时期,波斯王大流士出动10万大军入侵希腊,斯巴达国王不顾理事会的反对,带领300斯巴达战士(由 于没有得到理事会的同意,所以根据法律,他只能带这么多)到温泉关-波斯大军必经之路-守卫。他们利用地形和丰富的作战经验几次击败波斯大军,但终因寡不 敌众最后全部牺牲。影片中几段对话很有意思:

侦察兵:你不知道波斯军队,我在山上数他们的人数,数了整整六天!他们的人还在不断到来!到了夜晚,他们的帐篷和篝火像天上的星星一样多。
斯巴达国王:那太好了!我还是个孩子时就梦想着我手中的剑有一天能刺到星星。


波斯使者:我劝你们还是投降吧,一旦明天我们强大的军队开始进攻,我们射向天空的箭会把太阳都遮住。
斯巴达国王:(片刻沉默)那我们就在阴影下战斗。
c语言通过动态链接库调用c++函数c++调用c函数是比较简单的,但c调用c++函数则要麻烦一些,除了用动态链接库,我暂时也没有找到其它方法.

// vector.cpp:

#include <vector>
#include <string>

using namespace std;

extern "C"
{

void vector_add_string(char* str);
void vector_list_strings(char* buff);

vector<string> _stringList;

void vector_add_string(char* str)
{
_stringList.push_back( string(str) );
}

void vector_list_strings(char* buff)
{
int len=0;

for( vector<string>::iterator it=_stringList.begin();it!=_stringList.end();++it)
{
strcpy( buff+len,(*it).c_str());
len+=it->length();
}
}

}

编译程动态链接库:
g++ -shared -o vector.so vector.cpp

// test.c

#include "stdio.h"
#include "dlfcn.h"

void (*add)(char*);
void (*list)(char*);

int main(void)
{
char buff[1024];

void *dp;
dp=dlopen("./vector.so",RTLD_LAZY);

add=dlsym(dp,"vector_add_string");
list=dlsym(dp,"vector_list_strings");

add("hello");
add("bye");

list(buff);

printf("%s",buff);

return 0;
}

编译:
gcc -rdynamic -s -o test test.c -ldl
(注意: -ldl 是必须加的)

1.分两个程序:boot.asm 和 prog.asm其中boot.asm负责将软盘中第2个扇区开始的内容载入内存的 1000:0的地址然后跳转到此。而prog.asm负责进入实模式并输出字符"A"

2.使用nasm编译,用partcopy拷入软盘(或镜像),用bochs启动。

3.源代码:

boot.asm:

[org 0x7c00]
jmp start

start:

mov ax,cs
mov ds,ax
mov es,ax

reset:
;重置软驱
mov ax,0
mov dl,0
int 13h

jc reset

read:
;从第二个扇区开始读,将其后六个扇区的内容读到内存 0x1000:0 的位置
mov ax,1000h
mov es,ax
mov bx,0h

mov ah,2
mov al,6
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 13h

jc read

jmp 1000h:0h

times 510-($-$$) db 0
dw 0AA55h


prog.asm:

[org 0]

[bits 16]
mov ax,cs
mov ds,ax

jmp init
gdtr :
dw gdt_end-gdt-1 ; gdt的长度
dd gdt+0x10000 ; gdt的物理地址
gdt
gdt0 ; 空描述符
dd 0
dd 0 ; 所有的段描述符都是64位的
codesel equ $-gdt ; 这是8h也就是gdt的第二个描述符
code_gdt ;代码段描述符
dw 0x07ff ; 段描述符的界限是4Gb
dw 0x0000
db 0x01
db 0x09a
db 0x0c0
db 0x00

datasel equ $-gdt
data_gdt ;数据段描述符,这里只是写出来,并没有使用
dw 0x07ff
dw 0x0000
db 0x01
db 0x092
db 0x0c0
db 0x00

videosel equ $-gdt
video_gdt ;视频缓冲区的基址
dw 0xffff
dw 0x8000 ; 基址是0xb8000
db 0x0b
db 0x92
db 0xc0
db 0x00
gdt_end


[bits 16]
init:

mov ebx,0x10000
mov ecx,gdt

protect:

cli
lgdt [gdtr] ;加载GDT

push ax ;开A20线
in al,92h
or al,00000010b
out 92h,al
pop ax

mov eax,cr0 ;置位,切换到保护模式
or al,00000001b
mov cr0,eax

jmp codesel:code_32 ;跳入32位代码

[bits 32]
code_32:

mov ax,videosel
mov gs,ax

mov word[gs:0],0x0741 ;输出白色大写字母'A'

over:
jmp over

times 2048-($-$$) db 0

#TITLE=ASM
;===================================================================
; 80x86
; Assembly Language Syntax File
;
; Written
; by
; Chris Hobbs
;
; Owner: Lightning Software
; Http://www.fastsoftware.com
;
; This file is provided as a syntax file for ASM source code.
; It has been arranged for MASM code but will highlight
; most TASM/NASM code as well. Some special cases may exist in the
; keywords that you will need to change.
;
; The keywords are arranged as follows:
;
; 1 - Pseudo-Ops
; 2 - Mnuemonics
; 3 - Types
; 4 - MASM High Level Syntax
; 5 - Registers
;===================================================================


#DELIMITER=,[]-+*%/="'~!&|<>?:;#()
#QUOTATION1='
#QUOTATION2="
#CONTINUE_QUOTE=n
#LINECOMMENT=!
#LINECOMMENT2=;
#LINECOMMENT3=#
#COMMENTON=/*
#COMMENTOFF=*/
#COMMENTON2=
#COMMENTOFF2=
#ESCAPE=
#CASE=n
#PREFIX1=
#PREFIX2=
#PREFIX3=
#PREFIX4=
#PREFIX5=
#SUFFIX1=
#SUFFIX2=
#SUFFIX3=
#SUFFIX4=
#SUFFIX5=

;==========================================
; These are the psuedo-ops
;==========================================
#KEYWORD
COMM
CATSTR
@CATSTR
ORG
END
EQU
ALIGN
ASSUME
.CODE
.CONST
.CREF
.ERR
.ERRB
.ERRNB
.ERRDEF
.ERRNDEF
.ERRDEFI
.ERRIDNI
.ERRE
.ERRNZ
.NOCREF
.MODEL
.RADIX
.DATA?
.STACK
ECHO
ENDM
ENDS
TEXTEQU
EXITM
EXTERN
EXTERNDEF
FOR
FORC
GOTO
INCLUDE
INCLUDELIB
INVOKE
@INSTR
INSTR
LOCAL
MACRO
OPTION
CASEMAP
LANGUAGE
LJMP
OFFSET
PROC
PROLOGUE
EPILOGUE
SCOPED
NOSCOPED
PROTO
PUBLIC
PURGE
PUSHCONTEXT
POPCONTEXT
RECORD
REPEAT
REPT
STRUCT
SIZESTR
@SIZESTR
SUBSTR
@SUBSTR
TYPEDEF
UNION
USES
IFB
IFNB
IFDEF
IFNDEF
STRUC
ADDR
SIZEOF
PTR
;==========================================
; End of the psuedo-ops
;==========================================

;==========================================
; These are all of the mnuemonics
;==========================================
#KEYWORD
AAA
AAD
AAM
AAS
ADC
ADD
ADDW
ADDL
AND
ANDB
ANDW
ANDL
ARPL
BOUND
BSF
BSFL
BSR
BSWAP
BT
BTC
BTR
BTRL
BTS
CALL
CBW
CDQ
CLC
CLD
CLI
CLTS
CMC
CMP
CMPW
CMPL
CMPS
CMPXCHG
CWD
CWDE
DAA
DAS
DEC
DIV
ENTER
ESC
HLT
IDIV
IMUL
IN
INB
INW
INC
INCW
INCL
INS
INT
INTO
INVD
INVLPG
IRET
IRETD
JCXZ
JECXZ
JMP
JMPI
LAHF
LAR
LDS
LEA
LEAVE
LES
LFS
LGDT
LIDT
LGS
LLDT
LMSW
LOCK
LODS
LOOP
LOOPE
LOOPZ
LOOPNZ
LOOPNE
LSL
LSS
LTR
MOV
MOVB
MOVW
MOVL
MOVS
MOVSX
MOVZX
MUL
NEG
NOP
NOT
NOTL
OR
OUT
OUTB
OUTW
OUTS
POP
POPW
POPL
POPA
POPAD
POPF
POPFW
POPFL
POPFD
PUSH
PUSHL
PUSHA
PUSHAD
PUSHF
PUSHFL
PUSHFD
RCL
RCR
REP
REPE
REPZ
REPNE
REPNZ
RET
RETF
ROL
ROR
RORL
SAHF
SAL
SHL
SAR
SBB
SCAS
SETAE
SETNB
SETB
SETNAE
SETBE
SETNA
SETE
SETZ
SETNE
SETNZ
SETL
SETNGE
SETNL
SETGE
SETLE
SETNG
SETG
SETNLE
SETS
SETNS
SETC
SETNC
SETO
SETNO
SETP
SETPE
SETNP
SETPO
SGDT
SIDT
SHL
SHR
SHLD
SHRD
SLDT
SMSW
STC
STD
STI
STOS
STR
SUB
TEST
TESTL
VERR
VERW
WAIT
FWAIT
WBINVD
XCHG
XCHGL
XLAT
XLATB
XOR
XORL
JA
JAE
JB
JBE
JC
JGE
JE
JG
JL
JLE
JNA
JNAE
JNB
JNBE
JNC
JNE
JNG
JNGE
JNL
JNLE
JNO
JNP
JNS
JNZ
JO
JP
JPE
JPO
JS
JZ
;==========================================
; End of the mnuemonics
;==========================================

;==========================================
; These are all of the types
;==========================================
#KEYWORD
DB
DW
DD
DF
DQ
DT
BYTE
WORD
DWORD
FWORD
QWORD
TBYTE
SBYTE
SWORD
REAL4
REAL8
REAL10
SDWORD
;==========================================
; End of the types
;==========================================

;==========================================
; These are all of the MASM HL syntax
;==========================================
#KEYWORD
.BREAK
.CONTINUE
.IF
.ELSEIF
.ENDIF
.ELSE
.REPEAT
.UNTIL
.UNTILCXZ
.WHILE
.ENDW

#KEYWORD
.word
.long
.quad
.fill
.align
.globl
.text
.data
.bss
.byte
.ascii
;==========================================
; End of the MASM HL syntax
;==========================================

;==========================================
; These are all of the registers
;==========================================
#KEYWORD
AL
AH
AX
BL
BH
BX
CL
CH
CX
DL
DH
DX
SI
DI
ESI
EDI
EAX
EBX
ECX
EDX
CS
DS
SS
ES
FS
GS
SP
BP
IP
EIP
;==========================================
; End of the registers
;==========================================
        项目要求对某个串进行blowfish的加密,而php又没有现成的blowfish加密算法(好像是有一个,但需要重新编译PHP,太麻烦了,公司几十台机器,没空一台台的编译),于是在blowfish的网站上下了源代码,再根据PHP Module的框架,写了一个简单的Module。
        遇到的第一个麻烦是:blowfish是对64bit数据进行加密的,长的待加密串必须切分成8个字节一组进行加密,但如果要加密三个字符串,那该怎么办?在网上找了好一阵才知道:后面补零。
        但不久又遇到一个麻烦:对一段字符加密后再解密发现还原不了,更糟糕的是有的字符串是这样,有的字符串却又能还原。晕。问了苏宁,他也觉得匪夷所思。最后才想到原因:PHP Module里二进制串直接赋值是不可靠的,必须先base64进行encode!也就是说blowfish加密后面必须紧跟base64的encode,不然得出的二进制串是难以直接使用的。
        写PHP Module还挺长见识,对了,我可以为FlatDB也写一个PHP Module来方便调用。

关于存档

This page is an archive of entries from 08 2007 listed from newest to oldest.

07 2007 is the previous archive.

09 2007 is the next archive.

Find recent content on the main index or look in the 存档 to find all content.