双木成林:喋喋不休

I leave no trace of wings in the air, but I am glad I have had my flight.

用命令行编译Objective-C程序

without comments

此文来自本人原JavaEye博客,原文地址

最近在看Objc的开发,虽然Xcode很好用,但是还是不太习惯这种大型的IDE开发。 于是自己尝试着在Terminal下面编译。 先是最简单的一段程序。

#import <Foundation/Foundation.h>  

int main(int argc, const char *argv[])
{
    NSLog(@"Hello, World!");
    return 0;  

}

直接 gcc helloworld.m,报错。

错误提示如下

Undefined symbols:
  "___CFConstantStringClassReference", referenced from:
      cfstring=Hello, World! in ccCxrkF8.o
  "_NSLog", referenced from:
      _main in ccCxrkF8.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

猜测可能lib的位置不对,于是find了一下“Foundation”这个framework的位置,用以下命令编译:

gcc helloworld.m -L/System/Library/Frameworks/Foundation.framework/

还是一样的错误。

无奈之下man gcc从头看到尾。又去google了一下gcc for macosx。发现有一个-framework的选项。尝试了一下。

gcc helloworld.m -framework Foundation

终于成功了

2010-04-22 19:11:11.643 a.out[8932:903] Hello, World!

总结一下:macosx下面,objc的系统调用都是集成在framework里面的,要想编译的话,就必须用-framework选项将framework包含进来才行。

Written by linluxiang

二月 21st, 2011 at 8:28 下午

Posted in iOS,技术

Tagged with

MacOSX中链接boost库

without comments

此文来自本人原JavaEye博客,原文地址

今天在编译一个用到boost_program_options的库的时候出现了一点点小问题。总是提示说找不到boost_program_options这个库。

去/usr/local/lib下面看了一下,发现原来改名成libboost_program_options-mt.dylib了。搜了一下名字中这个mt的意思。

原来是boost1.33的新特性,就是区分了某些lib是单线程或者多线程的。这个区分导致必须显式的指明使用的是多线程还是单线程的库。

自然mt就是指的多线程,st指的单线程。

改用-lboost_program_options-mt以后,编译ok。问题解决。

Written by linluxiang

二月 21st, 2011 at 8:19 下午

Posted in C++,技术

Tagged with

如何使用logger将错误信息输出到日志

with one comment

此文来自本人原JavaEye博客,原文地址

今天在做分析http错误请求处理的时候遇到一个问题:当发生500错误的时候,如何将错误输出到日志当中呢?

搜了一下python的doc,在logging模块中有不起眼的一行代码提供了解决方案。

mylog.error('error!', exc_info=True)

其中,mylog就是Logger实例,当exc_info设置为True的时候,logger就会自动的调用sys.exc_info()函数,将traceback的信息打印到日志中。

Written by linluxiang

二月 21st, 2011 at 8:12 下午

Posted in Python,技术

Tagged with

求职总结

without comments

此文来自本人原JavaEye博客,发表于2009年10月26日。原文地址

好吧, 求职总算告一段落了.

从13号参加第一场笔试, 到24号拿到网易游戏offer, 20天时间的经历, 算是人生一大笔财富了.以后可能就没有这样的机会去体验那种心情了.
写一点总结, 希望能够帮助仍然在水深火热之中的同学和朋友.

一. 职业规划

求职的头等大事, 就是树立一个详细完整有可行性的职业规划.

其实职业规划, 不能是等到求职的时候才去想, 它的作用应该是指导大学4年期间学习方向, 以及指导工作以后的研究方向, 甚至可以决定一生的奋斗方向.所以, 最好在进大学1-2年内就确定自己的职业规划, 为之去努力, 然后在求职的时候, 针对你想进入的公司简单修改.不过这就属于是求职技巧的内容了.

职业规划我个人认为应该包含以下几个部分.1.我想要从事什么行业. 2.我想进这个行业内的哪些公司. 3.我进这些公司以后想要从事什么岗位. 4.我进公司以后应该怎么奋斗. 以上几个部分, 必须有足够能说服自己的理由.说服自己是关键, 别人的意见可以作为参考, 但是一定要有自己的观点.

  1. 就拿我自己来说吧, 我想从事互联网行业, 因为互联网行业是中国目前发展最快的行业之一, 可能甚至没有之一.
  2. 我想进的公司有, Google:互联网老大, 不用多说;网易游戏:中国自主研发实力最强的游戏公司, 而游戏行业是互联网行业中产值最大的部分;百度, 阿里巴巴, 腾讯:中国互联网三强, 产值过千亿的公司.
  3. 我想要从事的岗位是基于Unix或者linux平台的服务器端网络程序开发.因为自己是Open Source的狂热爱好者, 而且类Unix平台的服务器的市场占有率相当高.网络, 是未来的发展方向, 我们的生活必将和网络紧密结合, 以后, 上网这个词一定会消失或者变成纪念, 因为我们无时无刻不在上网.
  4. 进入公司以后, 我希望在4-5年内做到部门leader, 哈哈!

提过了愿景, 实现情况就是, 我已经满足了前三点, 第四点, 我一定会努力去实现它的.

关于想进的公司, 其实google还是心中永远的向往, 可惜google不招人啊…囧..剩下4个, 网易游戏和阿里巴巴的offer到手, 百度和腾讯被鄙视..恩.可能是骂百度太多败了不少人品吧..呵呵..

在面试中, 总会被不停的问到有关职业规划相关的问题.这个时候, 一个清晰明确的规划就十分重要了.当然, 要针对每个公司修改, 不能把面试google的回答去回答百度的问题, 那样不被刷才怪. :)

二. 简历

简历有两种, 一种是在网上招聘系统填写的在线简历, 另一种是自己精心制作的, 面试时候面试官会盯着问的简历.

网上申请时在招聘系统内填写的简历, 其实个人感觉不是很重要, 主要是系统用来刷一帮笔试名单用的. 面试官不会看.而且, 就算这一关被刷了, 也可以去霸王笔么. :)

真正重要的, 是自己精心制作的简历. 简历最好大概2-3页大小, 包括个人信息, 获得奖项, 项目经验等等. 对于偏技术类的岗位, 我认为, 项目经验是最重要的, 因为面试官会不厌其烦的问你项目相关的事项, 而且几乎全部的面试官, 都喜欢问你最不熟悉的那个项目. :)

关于写什么项目, 其实非常重要. 因为2-3页纸有限, 对于项目多的同学来说, 可能根本不够. 取舍就显得很重要了. 尽量把重要的, 与你所应聘的职位相关的项目写上去, 当然, 写上去的项目, 你的内心必须对这个项目无比熟悉. 因为这个项目就是一个大大的陷阱, 是我们设下的陷阱, 让面试官跟着我们的思路问问题的陷阱. 如果陷阱把老虎引过来了, 自己却没有办法制服老虎, 那么被老虎吃了就是唯一的下场. 当然, 风险大收益也大, 如果这个问题答的好, 面试官那里的得分可是会大大增加的.

另一点关于简历项目的要点就是, 你的简历项目, 必须能够证明你能在一个团队内良好的与同事合作. 也就是说, 一个人参与的项目, 除非巨牛, 不然少写, 突出团队项目就要多写, 而且注意, 不是突出自己在团队中的重要性, 而是作为一整个团队所获得的成绩的项目.

其他关于简历的注意事项, 不一定一个公司一个简历, 如果你把自己所有的精华都写在一个简历里面, 那么拿着这个简历就可以了. 当然, 简历里面不能有错别字啊. :)

三. 笔试

其实我个人还是比较恐惧笔试的, 因为我不知道笔试要考什么内容, 而面试我大致清楚面试官会问什么, 呵呵.

笔试题大多有以下几种:

  1. 专业题, 计算机相关专业, 就是数据结构与算法, 树, 链表, 字符串操作居多, 外加一些操作系统, 计算机网络的基本知识. 当然,如果你应聘的是dba, 或者sa, 就有一些特殊的题目, 比如sql啊, unix命令之类的. 语言基本上就是C或者C++, 很多招聘Java的职位, 考的试卷也是C++的.这个始终让我觉得很囧.
  2. 能力题, 能力题大致包括逻辑题, 智力题等等. 逻辑题比较容易做. 智力题的话, 也只有题海战术了, 网上多搜搜这个公司前几年的考题就一般能够找得到.

其实笔试考的好坏也不是很重要, 如果笔试没有进, 那么你就得把笔试题记住, 然后大胆的去霸王面把! 因为霸王面一定会问你, 你考试的时候觉得做的不好的是什么题? 回来以后有没有考虑过怎么做?

四. 面试

面试我想分开来谈, 呵呵, 因为面试太多, 不同的面试方式都不一样.

不过有几个词是通用的: 诚信, 团队, 本色!

另外, 和面试官要不亢不卑, 态度谦和. 多说谢谢是不会错的.

另外, 面试某公司面前, 应该去了解这个公司的用人原则, 或者他们创始人的名言之类的, 这个会在一定的时候, 收获奇效哦!

五. 专业面试

专业面试, 关键点就是把面试官吸引到你希望他问的方向上面.

当然, 如果你不知道面试官会问你什么问题的话, 那就应该找一家公司做试验, 看看他们的面试官会问你什么. 其他的公司大多数是差不多的. 对我自己来说, 可怜的千橡就成为了我的试验品了.

从试验公司知道了会问的问题以后, 回来立刻投入准备, 必须马不停蹄. 如果面试官问的是基础知识, 回来立刻背概念, 基础知识; 如果问项目, 回来把项目代码看一遍把关键技术要点思考一遍. 当然, 最好2个都做.

事实上这一招很有效, 在整个求职过程中, 我被问了4遍TCP三次握手.. – -!

然后要做的就是每次面试以后, 不断的复习这次面试过程中没有回答出来的问题, 强化记忆. 比如我第一次遇到select和epoll的区别的问题时候没有回答出来, 回来以后详细的看了一下, 后面的面试里面又被问了3次, 就回答的很好了.

最后要强调, 基础是非常重要的, 因为靠准备是不能准备全部的知识的, 只能平时积累了.

面试官最喜欢做的事情, 就是抓着你支支吾吾回答不清的地方问. 所以遇到自己不熟或者忘记的地方, 一定要果断的说, 不知道或者不清楚. 当然, 如果他问的问题全部都不知道, 可能就应该考虑自己知识点是否存在漏洞, 在面试回来就应该好好修补一下.

关于专业面试, 其实功夫还是在场外啊, 面试最重要的也就是把面试官引导到你熟悉的地方, 其他能做的, 就是好好的回答问题吧.

六. 群面

群面, 又叫做无领导小组讨论, 或者是AC面. 就是一帮人坐在一起讨论一个问题, 最后得出结论. 考核组员的合作能力, 处理争执的能力, 以及逻辑思维能力, 细心程度等等. 考察的东西相当的多.当然注意点也非常的多.

原来还以为面技术的不需要过群面, 结果网易游戏还是给了我这个机会让我体验了一把群面的感觉.

关于群面的考核目标里面, 我没有说结论的正确与否也是考核的目标. 因为很多讨论根本就是没有正确结果的, 所以无结果, 或者结果不能让所有人满意是很正常的情况. 大家也不要对群面的结果斤斤计较. 群面, 最重要的是过程.

群面的技巧, 按我的理解, 可以总结为以下几点, 不当出头鸟, 不当末尾兵, 说话平和, 面带微笑, 多多的鼓励人, 不要多说一句废话.

不当出头鸟是因为, 讨论的过程之中, 大家会自发的形成一个小团队, 团队必然有leader, 当然, leader不是这么好当的, 因为leader是面试官关注最多的人, 任意一点表现的不好, 都会导致得分的下降, 甚至不能进入下一轮面试. 所以, 如果觉得自己能力有限, 就不要当leader, 否则必败无疑.

不当末尾兵, 是指尽量不要当总结陈词的人. 因为总结的人对于其总结能力, 逻辑思维能力的要求非常高, 如果因为总结而导致逻辑错误, 或者说话支支吾吾, 等等状况的出现, 都会让面试官给你减分.

说话平和, 是说语气要平缓, 不急不躁, 让人听清为准, 不能像吵架一样语无伦次.

面带微笑, 这个是基本常识了.

多多鼓励人, 就是比如当主持人说, 请大家评价一下某位同学, 或者说, 大家评价一下这次面试的时候, 一定要说好的地方. 比如, 这位同学能力很强, 或者说, 某某同学时间控制的很好, 用正面的眼光去看人.

不说废话, 不是说不要当说话最少的人, 而是说说的话必须在点子上. 当整个队伍都是强人的时候, 很可能你的观点是和别人相同的, 这个时候可能就会觉得很尴尬, 自己的话都被别人说了. 那么, 着眼点就可以放在其他地方而不是结论的得出上. 比如, 提醒大家一些细节的小地方等等. 或者, 调控场面气氛等等.

群面其实还是比较能够测试一个人的性格特点的, 面试的时候什么状况都会出现, 大家记得保持冷静就是了.

最后再次强调, 谢谢不离口, 时刻保持微笑.

七. HR面

HR面往往是面试的最后一关, 一般来说, HR只有否决权没有决定权, 所以只要不犯大错误, 基本上offer就到手了.

HR面试的问题, 一般就是你的人生规划, 你最得意到事情, 最失意到事情等等, 大家到应届生网站上面可以查到一堆到问题. 所有问题到回答总结起来就是一句话, 千万不要和HR交心(借用浩哥的原话, 嘿嘿).

因为HR毕竟还是代表公司的, 如果这个时候放松了警惕, 说了一些不该说的话, 最后失意的也只有自己.

所以, 谈论自己缺点等等的时候, 就放一些无关紧要的缺点, 万金油的回答就是, “我觉得我的缺点是学习的东西偏重理论, 实践经验不足”. 这句话真是屡试不爽啊..大家一定要从中看到WS的地方, 深刻领悟之.. :)

另外, HR面还会看你是不是真的想要去他们公司工作, 如果你面试阿里巴巴, 言必谈及马云曾经说过blahblah, 我想, HR那里你的好感分会大大的增加. :)

还有一点要注意, HR面的时候, 你得时时刻刻表现出自己是团队的一份子. 比如说你最得意的项目之类的, 就一定要举出一个团队合作的例子, 尽量少搞个人英雄主义, 那是20年前的事情了.

要注意的是, 最后结束时候HR会问有没有问题要问我, 别忘了面试还没有结束, 你还是要表现自己非常想去他们公司, 还是有一个万金油的回答, “如果我拿到offer, 能不能马上过去实习呢”

哈哈, HR面一定要脸皮厚啊, 大家千万记住哦. 这是黎明前的黑暗, 光明就在眼前.

八. 感谢

好吧, 真心的感谢这段时间来给我鼓励, 陪我渡过难忘岁月的朋友们. 你们都是我的好兄弟或者姐妹. 以下感谢名单排名不分先后.

浩哥, mapx, 老万, 张师傅, reck, 老邓, 刘姐姐, 子, 波波, 小胖, 小威等等…以及所有帮助过我, 鼓励过我的人!

再次表示衷心的感谢…肺腑之言啊!

最后, 祝愿所有还在为了自己的理想奋斗的同学们, 加油! 要坚信, 自己一定会成功的.

Written by linluxiang

二月 19th, 2011 at 1:45 上午

Posted in 总结,技术

Tagged with

优化Python的DES加密程序有感

without comments

此文来自本人原JavaEye博客,发表时间2009年3月24日,可能有些东西现在看来是过时的,甚至是错误的,不过为了保证原来写的时候的感觉,所以没有修改。只在括号中注明了现在的看法。原文地址

最近信息安全的老师布置了作业。要求实现DES算法。。写了1天,优化了1天。。。小有些心得。。
首先感慨一下DES算法。。真是对人对机器都不友好的算法。。竟然还有诡异的S-BOX操作。。。
第二感慨一下Python对2进制不那么方便的支持。。连bin函数都没有。。虽然3.0有了。。可惜2.5没有。。只能自己实现,一大损失效率的地方啊。

好,接下来说说优化过程。

首先是单线程改多线程。。原来是将明文分成64bit一块的序列,每块单独加密。改成每一个64bit的块开一个线程操作。(这个在今天看来完全搞笑)

单线程加密解密一个1000长度的字符串所需时间大致和多线程加密10000长度的相等。效率提升明显。(提升效率很奇怪,忘了自己当初怎么测试的了)

其次是优化异或过程。原来的异或是整体将字符串转成整数然后再异或,发现效率很低。第一次修改为将2个字符串的每一位单独取出转成整形以后异或,效率提升不明显。后来上课时候突然想到,异或操作其实完全可以抛弃整数。1位的2个字符串的异或操作只有4种,写一个字典,用想要异或的2个字符串作为key,结果作为value。简单实现了一下。

def Xor(s1, s2):
    """
    字符串xor 

    s1 -- 第一个字符串
    s2 -- 第二个字符串
    """
    data={}
    data['0','1']=data['1','0']='1'
    data['0','0']=data['1','1']='0'
    s=[data[s1[x],s2[x]] for x in range(0,s1.__len__())]
    return ''.join(s)

三就是优化10进制转2进制。因为python没有提供 bin 函数。于是自己实现了一个。

dec2bin = lambda n:''.join([hex2bin(x) for x in hex(n)[2:].rstrip('L')]

但是在用profile做测试的时候发现的。程序运行中大量的用到了这个函数。很占cpu时间。经过观察发现主要是2个地方使用很多,第一就是异或操作的时候,因为python提供的异或只能在整数之间进行,第二就是在S_BOX运算的时候。

异或操作已经优化了。不需要10进制转2进制了。。剩下就是S_BOX运算了。经过观察发现,S_BOX里面最大的数也不过 15,于是想到可以穷举所有S_BOX里面的数字的值对应的二进制。更改代码如下。

def easyDec2Bin(s):
    """
    简单的10进制转2进制,用于简化s_box操作 

    s -- 10进制数
    """
    data={0:'0000',1:'0001',2:'0010',3:'0011',4:'0100',
              5:'0101',6:'0110',7:'0111',8:'1000',9:'1001',
              10:'1010',11:'1011',12:'1100',13:'1101',14:'1110',
              15:'1111'}
    return data[s]

第四步优化也是通过profile发现的。。发现程序运行过程中,大量的时间消耗在一个lambda函数上。

b= ''.join(map(lambda x:data[x],s))

这个函数的作用是生成一个字符串。。尝试着把这个lambda函数改成列表操作。

b= ''.join([data[x] for x in s]

效率提升明显。。。原来一直以为map操作比较快。看来并非如此。难怪Guido大叔要推广列表操作了。。

最后一步优化就是用了psyco模块,将程序变成JIT的。。效率提升很大。。。(现在看来其实这一步是最关键的。自己当初好傻)

最终优化的结果就是,加密解密1个40k的文件,原本需要将近50秒的时间,现在10秒不到就完成了。。。。

效果提升明显。不过总觉得还有提升的空间。。尝试把多线程改成Stackless版本的试试看。。。。希望能有更大的提高 。。。。(这句话现在看来完全是搞笑,看来当时的自己还是很稚嫩啊)

Written by linluxiang

二月 19th, 2011 at 12:59 上午

Posted in Python,技术

Tagged with

Django的Middleware开发有感

without comments

此文来自本人原JavaEye博客,发表于2009年2月26日。原文地址

Django应该算是目前最火的Pyhton的Web框架了把。个人感觉,超级方便的ORM,清晰而功能明确的分层以及Killer级别的后台管理都让习惯了Java那一套庞大复杂的人有了眼前一亮的感觉。

不过用久了就会发现,django整个框架之中有一个极其繁琐的地方,就好像一块整洁的布上有一个污点一样,令人觉得不爽。

那就是他的URL机制。。当然,也有人非常喜欢他的URL机制,比如说十分的灵活。不过我个人总觉得还有改进的地方。

首先我认为必须要利用正则表达式这一点,这个是特色以及精华,并且确实十分方便,在我眼里属于不能更改的部分。那么自然而然改进的地方就是正则表达式和函数的映射了。

提出问题是一方面,解决问题就是更加重要的地方了。采用何种新的方式来替换原来的URL处理呢?我为此困扰了好久。直到有一天发现了limodou大牛的Uliweb框架。被它的简洁明了的URL方式吸引了。决定采用类似Uliweb的方式处理URL。实现的具体细节,就是用Django的中间件。

使用中间件自然有他的理由。研究官网的文档后发现,Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的。所以说我们要做的就是在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response。需要注意的是,因为我不舍得放弃Killer级别的Admin,所以必须要支持默认的URL配置方式。那么我们可以简化原来的设计思路,把中间件不能处理的Request统统不管,丢给Django去处理。简直是完美的解决方案。:)。同时也不得不赞一声Django的设计。

接下来的设计就是考虑URL和函数处理的问题了。这个时候应该感谢的就是Python强大的语法了。提供了Decorator这种机制来解决这个问题。那么设计的思路转变成,在Request到达Middleware的时候,Import所有INSTALLED_APPS里面的views.py,目的自然就是执行Decorator。而在Decorator内部,根据到达的Request获得其访问地址,然后和处理它的函数一起生成RegexURLPattern对象,储存在缓存中。然后对每个Request进行处理,符合规则的就调用函数处理,不符合规则的,就交给Django自己去处理了。

以下是一小段中间件代码。比较核心的部分了。其实代码量也不大。大家看看有没有实现的问题。

    def process_request(self,request):
        path=request.path_info  #获得request的地址
        urls=settings.INSTALLED_APPS  #获得当前安装的app的位置
        def myimport(path):
            try:
                __import__('%s.views'%path)  #读取所有app的views。。目的是注册request处理函数
            except:
                pass
        map(myimport,urls)   #执行所有
        callback=expose.getCallback(path)  #获取相应url对应的处理函数
        if callback:
            return callback[0](request)  #执行。。

整体设计大致如此,完成了0.1版本,已经放在我的代码库里面了.http://code.google.com/p/linllx/

目前还存在的问题就是。第一,对于需要命名分组的正则表达式的处理还不是很有头绪。第二,对于404错误的处理究竟要如何进行,目前的实现来看不是很好。请看见本文的牛人们提供一下思路。。

总得来说,Django中间件的开发并不像我想像中的那么难,甚至可以说,还是比较简单的。下一步着手开发一个类似于Java中的Filter的中间件把。。当然,这个还是需要继续完善的。。

Written by linluxiang

二月 19th, 2011 at 12:58 上午

Posted in Uncategorized,技术

使用greenlet中一点简单心得

with one comment

想要对greenlet的switch机制进行测试,于是写了以下这段代码。


from greenlet import *

def test1(x, y):
    print 'in test1'
    z = gr2.switch(x+y)
    print z
    print 'out test1'

def test2(u):
    print 'in test2'
    print u
    gr1.switch(42)
    print 'out test1'

gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch("hello", " world")

运行结果:

in test1
in test2
hello world
42
out test1

从这个层面可以看出。greenlet的协程其实是一个切换机制。就是主动将自己的运行过程让给别的协程。切换需要有目标,并且可以在switch里面传入参数。如果是第一次运行,switch的参数就是作为协程的run的函数的参数传入。如果是运行中,就作为switch的返回值。
以上隐含的内容是,如果在运行中想要切换到别的协程去做事,那么不能保证那个协程一定会返回结果。
考虑在greenlet上面加上一个隐含回复机制。

Written by linluxiang

二月 16th, 2011 at 2:08 下午

Posted in Python,技术

Tagged with ,