introduction to linux kernel tcp/ip procotol stack
nginx中http request处理的流程
这次主要来看nginx如何处理一个http的流程,也就是接收请求,解析,然后接收完毕,然后开始发送数据,这一系列是如何流转起来的,通过上2篇,我们知道了nginx初始化完毕之后会休眠在epoll(或者kqueue等等).
下面就是nginx的事件处理流程图.
nginx的启动流程分析(二)
接上篇,这篇主要来看nginx的网络部分的初始化
首先是ngx_http_optimize_servers函数,这个函数是在ngx_http_block中被调用的,它的主要功能就是创建listening结构,然后初始化。这里ngx_listening_t表示一个正在监听的句柄以及它的上下文。
1 |
|
nginx的启动流程分析(一)
这篇我们会主要来分析配置文件相关的一些初始化,而在下一篇我们会详细分析http协议相关,以及socket的初始化信息。
nginx启动最重要的部分是在ngx_init_cycle中,我们接下来就会详细的分析这个函数,以及相关的函数.
下面就是ngx_init_cycle的流程图
再见2010
一晃眼,2010就过去了,又要开始整理这1年读的书,看的电影,听的歌了。
2010 读过的书,今年很惭愧,看的书太少了,明年会更加努力。今年觉得最好的两本是天朝的崩溃和罗马帝国衰亡史.今后会把更多的时间分配给读书。
nginx中slab分配器的实现
nginx的slab分配器主要用于共享内存部分的内存分配,代码包含在core/slab.c和core/slab.h中。slab是针对小于1页的内存的fenpei 它的大体思想和jeff的那篇paper中描述的一致,因此可以先看看jeff的那篇关于slab的论文。有关于slab的优点也可以去看jeff的paper,这里就不描述了。
下面就是nginx的slab的内存图.
linux kernel 网络协议栈之xps特性详解
xps全称是Transmit Packet Steering,是rfs/rps的作者Tom Herbert提交的又一个patch,预计会在2.6.37进入内核。
linux kernel 网络协议栈之GRO(Generic receive offload)
GRO(Generic receive offload)在内核2.6.29之后合并进去的,作者是一个华裔Herbert Xu ,GRO的简介可以看这里:
http://lwn.net/Articles/358910/
先来描述一下GRO的作用,GRO是针对网络接受包的处理的,并且只是针对NAPI类型的驱动,因此如果要支持GRO,不仅要内核支持,而且驱动也必须调用相应的借口,用ethtool -K gro on来设置,如果报错就说明网卡驱动本身就不支持GRO。
GRO类似tso,可是tso只支持发送数据包,这样你tcp层大的段会在网卡被切包,然后再传递给对端,而如果没有gro,则小的段会被一个个送到协议栈,有了gro之后,就会在接收端做一个反向的操作(想对于tso).也就是将tso切好的数据包组合成大包再传递给协议栈。
如果实现了GRO支持的驱动是这样子处理数据的,在NAPI的回调poll方法中读取数据包,然后调用GRO的接口napi_gro_receive或者napi_gro_frags来将数据包feed进协议栈。而具体GRO的工作就是在这两个函数中进行的,他们最终都会调用napi_gro_receive。下面就是napi_gro_receive,它最终会调用napi_skb_finish以及napi_gro_receive。
linux kernel tcp拥塞处理之cubic算法
接上一篇(可以看我协议栈分析的那个pdf).这里我的内核版本是2.6.36.
这次主要来看一下内核拥塞控制算法cubic的实现,在linux kernel中实现了很多种拥塞控制算法,不过新的内核(2.6.19之后)默认是cubic(想得到当前内核使用的拥塞控制算法可以察看/proc/sys/net/ipv4/tcp_congestion_control这个值).下面是最新的redhat 6的拥塞控制算法(rh5还是bic算法):
1 |
|
这个算法的paper在这里:
linux kernel中如何保证append写的原子性
先来描述一下,write系统调用的大体流程,首先内核会取得对应的文件偏移,然后调用vfs的write操作,而在vfs层的write操作的时候会调用对应文件系统的write方法,而在对应文件系统的write方法中aio_write方法,最终会调用底层驱动。这里有一个需要注意的就是内核在写文件的时候会加一把锁(有些设备不会加锁,比如块设备以及裸设备).这样也就是说一个文件只可能同时只有一个进程在写。而且快设备是不支持append写的。
而这里append的原子操作的实现很简单,由于每次写文件只可能是一个进程操作(计算文件偏移并不包含在锁里面),而append操作是每次写到末尾(其他类型的写是先取得pos才进入临界区,而这个时间内有可能pos已经被其他进程改变,而append的pos的计算是包含在锁里面的),因此自然append就是原子的了.