08 2010存档

蜂蜜

| | Comments (2) | TrackBacks (0)

爸以前跑车,曾经在养蜂人那里买了一些野蜂蜜,香味扑鼻、非常浓稠,气温偏低就会结晶,确是正宗好蜂蜜。

我睡觉不沉,喝蜂蜜可以安神助眠,所以用量不小。现在蜂蜜快喝完了,爸又不可能为了买蜂蜜再回一趟家乡,超市里的蜂蜜不用考虑了,不知道兑了多少水,看着跟糖稀似的。琢磨着在北京附近有没有散装的好蜜出售。


于是乎,周五爸妈去了趟香山,顺路去了植物园,买了些蜂蜜。

我尝了尝新买回来的蜂蜜,也很香,喝了一点,

“不错,好甜......比家乡的那个要甜的多”

“可能是品种不同,不同的花,产出的蜜不一样” 爸一边回答一边看盒子上自己贴的标签:“这是枣花蜜......嗯,这是荆条蜜......”

家乡的蜜香味重甜味淡,似乎更极品,是什么花的蜜呢?我好奇的拿起老瓶子看了一眼标签,上面写着——

“遵义蜜”

客服琐记

| | Comments (2) | TrackBacks (0)
客户用我们提供的API时居然出现了程序死循环。

我们的API用户已经使用了快一年了,还从没遇到这种情况,多半应该是用户使用上的问题。所以我下楼去看看。

客户的问题很容易重现,但是我写了个一样的例子,却没有这个问题。

“我的例子跟你代码几乎一样啊”我问。

“是啊......不对,有点不一样,你是多进程,我是多线程的,你们的API里用到了read,而且还判断了errno是吧,errno在多线程下岂不是互相影响?”

他这么一说我还真有点怀疑了,虽然API已经被用了一年,但大多数人都是用的多进程(unix的优秀习惯,噢),这可能是大家都没发现这一问题的原因。

我跑去问架构师,说了一下我的怀疑。

“不会吧,linux上系统调用都有可能影响errno,那任何一个多线程程序岂不是都有这个问题?”

“对啊。。。”

我这个人很动摇,两头都在说我就两头都在晃。

架构师查了查errno的man,确实,errno是“thread local”的,一个线程一个errno,不会互相干扰。

干脆回去把我的例子改成多线程的,依然不能重现,这下就不是多线程的问题了。


最后用户突然想起他们有个线程比较特殊,它@X%X%@#¥%……&*,还是API使用上的问题。我松口气。

对自己写的kernel module进行压力测试,连续跑了24小时,没啥问题,但是,继续跑到30几个小时的时候,内核panic了。

从panic的信息看,是在dcache_readdir的时候,就是从cache里读各inode的时候遇到麻烦了。

kernel本身是很坚固的,肯定是我的module某个地方把cache里的东西弄坏了,想想我确实有遍历目录的操作:

next = dentry->d_subdirs.next;
while (next != &dentry->d_subdirs)
......

再仔细看看内核里dcache_readdir的实现,喔,我少加了锁,应该是:

spin_lock(&dcache_lock);
遍历目录
spin_unlock(&dcache_lock);

之前的panic应该是我遍历目录的同时系统在调整dcache,结果竞争了。

那些找实习或找工作都很顺利的、成绩优秀的、拔尖的、外企都抢着要的人才们,请忽略此文。

5年前我找实习,很艰难。最近招聘实习生,有一个我面试感觉还可以的实习生来了一封邮件,看此邮件,我感到既同情又无奈:

您好!

       我是xxx,上周二去贵公司面试了实习生的职位。到今天已经一周了,还是没有得到通知,应该是面试没有通过被默拒了吧。自己等的也比较着急。

       还是想冒昧的问一下:在面试时应该怎样表现,或者是怎样准备知识更好,能否给点建议。说实话,这三周实习的过程中悲剧了几次,但都不是很清楚企业筛选的标准。

       如果您有时间,就简单回复下吧。谢谢!


我回了邮件,原文贴在这里,一字不改:

您好:

        我刚问了leader,确实是拒了。

        就我个人来说,我觉得你的面试表现不错,基础知识比较扎实,回答也比较迅速得体,我挑不出什么明显的问题。但是,我只是公司一个普通程序员,不是管理层,决定不了你的去留。我问了你被拒的原因:各个项目组需要的是迅速能上手的人或者说专业对口的人,你专业不够对口,同时缺乏项目经验。

       你可能会觉得不公平:本来我就是找实习,怎么还要项目经验??本来我学的是软件工程,做的就是软件,有什么不对口的? 这个问题我也没有办法回答,我当年找实习一样也有这样的愤慨,但是世道艰难,5年了,也没人回答我。

        你邮件里的意思,你已经找了三周的实习而没有结果,这个你不用着急,我也是软件学院的,05年找实习的时候,花了将近两个月,面试过intel、sun、IBM还有很多你根本没听说过的小公司,最后是在3721公司(就是那个著名的流氓公司)实习。

        现在世道艰难,招聘公司也是挑肥拣瘦,所以花的时间肯定是越来越长,你的基础不错,所以不要太着急,小公司(甚至流氓公司)实习也可以考虑,只要是工作能长经验就好。

        对了,我们核心系统组拒了,但是测试组还在招实习生,你个人愿意干测试工作吗?相对开发工作,是要枯燥一些。


和我当年一样艰难的实习生们,你们也只能和我当年一样的继续艰难了。

真的不知道还能说什么。


====== 2010.08.11更新 ======
今早和leader再商量了一下,决定收这位实习生。先做一个月的测试工作适应团队,再考虑转为开发。
leader本身是出于好意:我们选择实习生除了专业选择,也要考虑我们带实习生的资源是否丰富。如果带的资源不够,那么实习生学不到东西,带的人疲惫,两边都不好过。
呵呵,我的回信有点夸张,至少我们招聘并非”挑肥拣瘦“,是双向选择,也有拒了我们的实习生。我这样直肠子的大炮,夸张就夸张了,大家慢慢习惯。

同时感谢大家的关心。

趣事二则

| | Comments (2) | TrackBacks (0)
7月底,桑拿天。

妈:昨晚热得不行了。我吹个电扇,你爸又嫌冷;我盖被单,你爸盖被子,没法过了。

我:要不买个空调吧。

妈:你爸吹个电扇都怕,还空调?!

我:这样,空调买回家,不用安装,内机对着你吹,外机对着爸吹,这样都满意了。



家里办理宽带通,两年,妈叫他们送点礼品,宽带通的人说没礼品,还说歹说送了个金山的杀毒软件。

几天后,家里的小床腾了出来,打算卖掉。

我:单卖可能卖不了多少钱。

妈:那就把床垫搭送了。

我:也没多少钱。

妈:那就买单人床一个,搭送杀毒软件一份。

项目一直是有自动化测试的,每天都跑一遍,把结果报告发给团队的每个人。

过去几个月自动化测试跑得都很顺利,太顺利了,每天都没有fail。

写这些用例的人有些离职了。

现在项目有大改动,很多自动case跑fail了,我们知道是哪个case fail,但是,这个case具体是做了些什么才fail的呢?没人知道了,测试人员、包括开发人员,都只能去看自动测试的code来找出原因和重现方法......这样,所谓“自动化测试”,变成了“半自动化测试”??虽然你能告诉我某个case出错了,但你没有告诉我是怎么出错的、怎样重现?

最基本的解决办法是在自动化测试的code里加入足够的用例说明,如果fail了,至少可以很快知道怎么去手工重现。唉,慢慢改吧。

内核模块里自己做了一个简化版的 find_get_page:

  struct page * my_get_page(struct address_space *mapping, unsigned long offset)
  {
      struct page *page;

      read_lock_irq(&mapping->tree_lock);
      page = radix_tree_lookup(&mapping->page_tree, offset);
      read_unlock_irq(&mapping->tree_lock);
      return page;
  }

代码是从2.6.18的内核里抄来的。

在2.6.9内核的xen虚拟机上测试,现象很诡异:服务器的ssh连接突然断开,只能重连,重连后看见模块被自动卸载掉了。仔细看代码,才发现2.6.9内核的struct address_space里的tree_lock是spinlock_t,而不是rwlock_t,结果我的代码就是对着一个spinlock_t调用read_lock_irq,锁操作不对,然后又发生了什么呢?

read_lock_irq 调用了 _raw_read_lock:

  static inline void _raw_read_lock(rwlock_t *rw)
  {
  #ifdef CONFIG_DEBUG_SPINLOCK
      BUG_ON(rw->magic != RWLOCK_MAGIC);
  #endif
      __build_read_lock(rw, "__read_lock_failed");
  }

喔,kernel会判断锁的magic number,不对的话会调用BUG_ON(),进而调用BUG(),所以机器打了个嗝。

如果没有这个magic number的检测,一旦死机,错误就更难找了,这个检测虽然很土,但很体贴,也很有效。

关于存档

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

07 2010 is the previous archive.

09 2010 is the next archive.

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