全部博文(41)
分类: LINUX
2009-08-27 09:50:08
tcp.c文件的tcp_dequeue_partial函数
978计划工作组
/*
* Locking problems lead us to a messy situation where we can have
* multiple partially complete buffers queued up. This is really bad
* as we don't want to be sending partial buffers. Fix this with
* a semaphore or similar to lock tcp_write per socket.
*
* These routines are pretty self descriptive.
*/
struct sk_buff * tcp_dequeue_partial(struct sock * sk)
{
struct sk_buff * skb;
unsigned long flags;
save_flags(flags);
cli();
skb = sk->partial;
if (skb) {
sk->partial = NULL;
del_timer(&sk->partial_timer);
}
restore_flags(flags);
return skb;
}
从partial队列中取数据包,如设置了超时定时器(partial_timer)则将其删除。
tcp_write
|__tcp_enqueue_partial
|__tcp_send_partial
|__tcp_dequeue_partial ->tcp_send_skb
skb->partial:此队列只缓存1个数据包,partial 队列中缓存的单个数据包源于TCP 协议的流式传输,对于TCP 协议,为了避免在网络中传输小数据包,充分利用网络效率,底层网络栈实现对于用户应用程序发送的少量数据进行收集缓存,当积累到一定数量后(MSS),方才作为整个包发送出去。partial 队列中数据包的意义即在于此,对于少量数据,如果数据并非是OOB 数据(即无需立刻发送给远端),则暂时分配一个大容量的数据包,将数据拷贝到该大数据包中,之后将该数据包缓存到partial 队列中,当下次用户继续发送数据时,内核首先检查partial 队列中是否有之前未填充满的数据包,则这些数据可以继续填充到该数据包,直到填满才将其发送出去。当然为了尽量减少对应用程序效率的影响,这个等待填满的时间是一定的,在实现上,内核设置一个定时器,当定时器超时时,如果partial 队列中缓存有未填满的数据包,仍然将其发送出去,超时发送函数为tcp_send_partial.。
skb->partial_timer:用于按时发送partial 指针指向的数据包,以免缓存(等待)时间过长。