一 要实现一个高效的流媒体服务器,离不开一个高效的网络协议栈,目前流媒体服务器大多是基于tcp/udp的,
我们可以从tcp/udp入手,逐渐深入,甚至开发自己的流媒体协议栈。
二 tcp 的三个接收队列
1 prequeue
在linux内核中,每一个网络数据包,都被切分为一个个的skb,这些skb先被内核接收,然后投递到对应的
进程处理,进程把skb拷贝到本tcp连接的sk_receive_queue中,然后应答ack。
以往的内核处理这些skb的时候,是直接通过内核调度的,有数据来了,就进行进程调度,这样虽然实时性高,但是会
导致进程阻塞,或者调度消耗大的问题。因此内核搞出来一个新的东西叫做,prequeue,skb先统一由内核接收,
然后通过内核原有的进程调度机制进行调度,当调度到某一个进程的时候,该进程发现prequeue中有skb属于自己,
于是把prequeue中的skb拷贝到本进程的sk_receive_queue中,并做ack应答。
这样一来,收发网络数据包,就不会引起进程调度了,虽然ack的时间可能会不那么及时,但是cpu的利用率实际上是
提高了。
2 sk_receive_queue
上面已经有所介绍,struct sock 的成员,进程处理prequeue的时候,把skb拷贝缓存到自己的sk_receive_queue中。
3 backlog
要理解backlog队列的含义,先理解对于一个listening socket,kernel维护的两个队列
未完成队列,指的是还没有完成tcp三次握手的连接的队列,socket状态是SYN_RCVD
完成队列,包含了哪些已经完成三次握手的连接,socket状态是ESTABLISHED
三 下一节我们讲讲tcp收发数据的过程
我们可以从tcp/udp入手,逐渐深入,甚至开发自己的流媒体协议栈。
二 tcp 的三个接收队列
1 prequeue
在linux内核中,每一个网络数据包,都被切分为一个个的skb,这些skb先被内核接收,然后投递到对应的
进程处理,进程把skb拷贝到本tcp连接的sk_receive_queue中,然后应答ack。
以往的内核处理这些skb的时候,是直接通过内核调度的,有数据来了,就进行进程调度,这样虽然实时性高,但是会
导致进程阻塞,或者调度消耗大的问题。因此内核搞出来一个新的东西叫做,prequeue,skb先统一由内核接收,
然后通过内核原有的进程调度机制进行调度,当调度到某一个进程的时候,该进程发现prequeue中有skb属于自己,
于是把prequeue中的skb拷贝到本进程的sk_receive_queue中,并做ack应答。
这样一来,收发网络数据包,就不会引起进程调度了,虽然ack的时间可能会不那么及时,但是cpu的利用率实际上是
提高了。
2 sk_receive_queue
上面已经有所介绍,struct sock 的成员,进程处理prequeue的时候,把skb拷贝缓存到自己的sk_receive_queue中。
3 backlog
要理解backlog队列的含义,先理解对于一个listening socket,kernel维护的两个队列
未完成队列,指的是还没有完成tcp三次握手的连接的队列,socket状态是SYN_RCVD
完成队列,包含了哪些已经完成三次握手的连接,socket状态是ESTABLISHED
backlog参数历史上被定义为上面两个队列的和
4 还有很多网卡,闲杂都支持napi,都是通过napi读取数据的,网卡接收多次数据才产生一次中断,减少中断服务次数,提高cpu效率
三 下一节我们讲讲tcp收发数据的过程