Kernel Space

February 6, 2007

编程点滴(1)

Filed under: 编程珠玑 — agassi @ 11:24 pm

自己写了一个传输层的library,结果没有经过仔细的测试就给别人用了,结果问题百出。其实自己写的Code就是烙上自己商标的商品,如果质量有问题,当然不能接受,同时也有损自己的“声誉”。更何况自己这个library用了自己以前从来没有用到的epoll和IOCP技术,就更有理由要仔细测试了。在编写测试程序的时候出现了一些问题,其实都是以前碰到过的问题,只是没有记录下来,现在又反复犯,看来这个Blog还是很重要的!!

  • 当要开大数组的时候最好用heap:今天要开一个16K的数组用于发送测试数据,结果图省事就开了一个16K的数组(因为栈比堆更高效的印象深深印在脑中)。后来程序就randomly的出现SEGFAULT(Under Linux)。dump出来的core file也没有任何信息含量。自己最终百思不得其解。结果问了高人才知道这个Linux有个系统堆栈大小,如果是内核编程应该在1K以内,这个用户模式也大不到哪去。后来换成heap就搞定了!! (好像修改 ulimit 的stack size也不管用)。
  • 跨module内存分配和释放最好使用global allocator:一直不明白STL的allocator自己什么时候用得到,今天就知道了。现在的程序分层很明显,然后一个层又是一个so文件或者dll文件,层和层之间需要传递数据。为了提高效率,通常不会使用频繁的数据拷贝,所以经常是一个内存块从底层开始引用到最高层。后果就是,上层模块在使用完内存后不能跨模块释放内存。今天就碰到了这个问题(至少malloc/free不行,M$的GlobalAlloc/GlobalFree好像可以,所以叫Global)。一个折中的办法就是分配内存的模块提供一个释放内存的函数,缺点就是这个函数需要被各个层包装起来。比较好的办法就是使用一个global的allocator,这个是个单独的模块,其他各个模块都可以引用,STL的容器就缺不了这个东东。以后有机会研究一下STL的allocator。(这里有个很好的讨论贴讨论跨模块内存分配释放 http://blogs.msdn.com/oldnewthing/archive/2006/09/15/755966.aspx这里再强调一下,跨module分配释放内存要特别注意,10天后的今天同样的bug发生在了别人身上,还浪费了几个小时去理解“Invalid Address specified to RtlValidateHeap”这个消息到底是什么意思。
  • 网络拆包要考虑周全:记得很久以前参加ACM比赛,一道训练题目就是模拟电梯程序。结果自己冥思苦想了N久才搞定,主要问题就是有太多逻辑分之需要考虑。其实拆包这个也不复杂,但是可能是自己退化比较严重,少考虑了一种情况,导致Access Violation。我考虑了收到部分payload的情况,漏掉了收到部分header的情况。可能是觉得header太小,估计不会分两次收到;而且Linux下确实没有出现这种情况,Windows的Socket就非得把缓冲填满了,然后通知程序,结果出现了这个问题。4个字节的header结果只有两个字节数据,还有另外两个字节在下一次接受。看来自己如果要做Testing还需要很多磨练啊。
  • 输出到屏幕和重定向到文件的区别(Linux):今天在调试的时候发现server端的输出重定向到文件总是不完全,发送100个包少输出2个,发送1000个少10个。。。但是如果只是输出到terminal屏幕不会出任何问题。而且每次运行同样的数据,输出文件总是break在同一行的中间。后来用了tee,让信息同时输出到屏幕和文件,结果还是同样的问题,而且屏幕输出都break了。看来是这个I/O重定向的问题,因为tee的输出还是会经过写文件。一怒之下,请出strace来帮忙。结果真相大白: 如果只是输出到屏幕,底层的write系统调用会把收到的信息马上输出到stdout上;反观I/O重定向,系统总是攒够了4K的字节才调用write写入到文件中,这是因为I/O操作本来就很慢,所以采用page size 大小作为缓冲。问题就出在server端最后调用了一个会sleep的函数,然后wait forever;结果就在系统准备把最后的几千个字节写入文件的时候,主线程进入了sleeping状态,导致写入失败(或者根本就是pending)。如果任务执行完后立刻退出,则输出文件就是完整的。看来sleeping的线程将停止一切活动,具体为什么有待查阅进程管理的内核有关章节!
  • High Speed Consecutive Sending:这个情况发生在Linux上。当连续不断的调用send的时候,系统会出现莫名其妙的SEGFAULT(莫名其妙表示corefile没有任何信息含量),个人认为可能程序flush了系统的socket buffer。所以我在每个send后面放了个usleep(1)。就是这一个microsecond,居然起了大作用。但是原因是什么自己还不清楚,也许这个usleep也是个治标不知本的办法。需要再多学习系统内核!!!

很多东西都是经验,自己真正动手写,动脑想才会真正理解一些别人的精妙的设计,才会使自己的编程能力有质的飞跃。

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: