凡是讲解OS内核的书,我基本都是打90分,尤其是国内作者写的。毕竟国内做IT的大部分就是混口饭吃,有时间专研,有精力专研,而且肯专研底层技术的
人,本身就值得钦佩和鼓励。
书里前几章讲linux内核的一些常用小组件(比如锁),其
中讲“内存屏障“的部分相当不错,来龙去脉讲得很清晰,帮我理清了一些以前混淆的概念。后面的几章里,“slub”分配器和“cfs调度”是内核较新的东
东,我重点看了看。其余讲内存和进程的和《情景分析》有所重复,没再细看。
书偏贵,加上内容有些宽泛,所以,推荐借阅。购买就有点贵了。
听冯大辉同学说, 现在国内原创技术类图书的出版不景气,因为购买者太少,成本都难收回来。确实,现在原创的技术文章更多的出现在博客和论坛上,买技术类图书的必要就不是很 大了。表面上看来,写书的人没了动力,出版业倒霉了,图书市场萎缩了,但实际上这样更好,更多的优秀技术文章在网络上免费共享了。免费的经验共享(不是盗版共享)会让一个行业更繁荣。写了个httpd服务,测试性能。
用curl发200k的请求,回复也是200k的消息,调用20次curl,花了30秒。
这性能看上去很低,但我发现httpd的CPU消耗也很低,那是慢在哪里了?
于是自己写了个client端,一次send 200k的消息,再收200k,重复1000遍,发现超快,几秒就完成了,server端httpd消耗的CPU也高起来了,占到70%,看来不是我写的httpd的问题,压根就是curl启动慢,白耗时间。
curl不适合用来做性能测试,http_load更适合,但它不带body,所以我改了改http_load.c,加了个参数 -body ,后面跟body的大小(单位是KB),比如:
./http_load -p 5 -s 600 -body 100 url.list
意思是5个并发,跑600秒,body为100k大,跑完后显示QPS几百,够了。
我改动后的http_load.c代码在这里,diff在这里。body的大小不能超过200k,因为我的测试足够了。另外还把SO_SNDBUF开到了最大(rhel4上是128k),因为想把200k一次send出去,这样改最方便。
于是按太太的意见,买了点健胃消食片和大山楂丸。
今天中午吃饭。
我: 昨天吃了消食片和山楂丸,胃好多了。
太太: 说明你胃没什么事儿,就是吃太快了,牛肉不易消化。
我: 但是何以肯定是牛肉呢?如果是bug,必须能重现才行,所以,我要再喝一碗牛肉汤。
太太: ....
使用http_load的过程中遇到了一个报错:Cannot assign requested address
网上找到了原因和解决方案 http://gcoder.blogbus.com/logs/41839731.html
但是要注意,这是客户端的问题,是客户端用光了端口号,所以要改客户端机器的配置和代码,不是改服务端的!
我在http_load.c里给socket加了一个SO_REUSEADDR,才能工作正常。为什么http_load不加上这个option呢?因为http_load测的是标准的http服务器,比如apache,这些服务端会关闭socket,而我测的是自己写的httpd,所以....看来细节很多啊。
pthread_t pthr;
pthread_create(&pthr, NULL, thread_handler, NULL);
...
void* thread_handler(void* arg)
{
/* do something */
pthread_join(pthr, NULL);
}
上面的代码不好使,pthread_join不能放在pthread调用的handler内,虽然不报错,但是thread无法正常回收,如果多次创建thread,内存会越来越大(另一种形式的内存泄露)。
正确的做法是在handler外面pthread_join:
pthread_t pthr;
pthread_create(&pthr, NULL, thread_handler, NULL);
pthread_join(pthr, NULL);
...
void* thread_handler(void* arg)
{
/* do something */
}
如果不用pthread_join,改用pthread_detach呢?那最方便,但要注意:pthread_detach最好是放在handler里面第一句。
void* thread_handler(void* arg)
{
pthread_detach(pthr);
/* do something */
}
如果pthread_create后紧跟pthread_detach,有可能会出错。
小心使用grep里的星号(*)
grep "/home/.*test"
上面这句是找出所有/home目录下,以test结尾的文件
grep "/home/*test"
这句可就不是了,这句grep只匹配以下的文件名:
/hometest
/home/test
/home//test
/home///test
看明白了,星号(*)代表重复其前面的字符任意次(包括零),而“/*“当然就表示重复”/”任意次。
另外注意grep后面的正则表达式务必加上双引号,如果不加,在一些特殊场合会有完全不同的含义。
比如我当前目录下有六个文件:
testa
testb
testc
testd
tt
t
运行:
ls -l|grep t*t
它会把这五个文件都列出来吗?不,结果显示只找到了文件tt
因为上面的shell命令,grep实际上是在找以t开头且以t结尾的文件(这一规则和ls的规则一样)
要想grep把后面的”t*t”当成正则表达式,需要加上双引号:
ls -l|grep "t*t"
这下结果ok了:所有六个文件都可以被找到。
