45-答疑篇:Linux网络性能优化答疑
问题1:网络收发过程中缓冲区的位置
网卡收发网络包时,通过DMA方式交互的环形缓冲区
- 网卡中断处理程序为网络帧分配的,内核数据结构sk_buff缓冲区
- 网卡中断处理程序为网络帧分配的,内核数据结构sk_buff缓冲区
首先,这些缓冲区的位置在哪儿?
是在网卡硬件中,还是在内存中?
这个问题其实仔细想 一下,就很容易明白——这些缓冲区都处于内核管理的内存中
其中环形缓冲区,由于需 DMA与网卡交互,理应属于网卡设备驱动的范围
sk_buff缓冲区,是一个维护网络帧结构的双线链表,链表中的每一个元素都是一个网络 帧(Packet)
虽然TCP/IP协议栈分了好几层,但上下不同层之间的传递,实际上只需要操作这个数据结构中的指针
而无需进行数据复制
套接字缓冲区,则允许应用程序,给每个套接字配置不同大小的接收或发送缓冲区
应用程序发送数据,实际上就是将数据写入缓冲区
而接收数据,其实就是从缓冲区中读取
至于缓冲区中数据的进一步处理,则由传输层的TCP或UDP协议来完成
其次,这些缓冲区跟前面内存部分讲到的Buffer和Cache有什么关联吗?
内存中提到的Buffer ,都跟块设备直接相关;而其他的都是Cache
实际上sk_buff、套接字缓冲、连接跟踪等,都通过slab分配器来管理
可以直接通 过 /proc/slabinfo,来查看它们占用的内存大小
问题2:内核协议栈,是通过一个内核线程的方式来运行的吗
第二个问题,内核协议栈的运行,是按照一个内核线程的方式吗?在内核中,又是如何执行网络协议栈的呢?
说到网络收发,其中的软中断处理,就有专门的内核线程ksoftirqd
每个CPU都会绑定一个 ksoftirqd 内核线程
比如2个CPU时,就会有ksoftirqd/0和ksoftirqd/1这两个内核线程
不过要注意,并非所有网络功能,都在软中断内核线程中处理
内核中还有很多其他机制 (比如硬中断、kworker、slab等)
这些机制一起协同工作,才能保证整个网络协议栈 的正常运行
问题3:最大连接数是不是受限于65535个端口
无论TCP还是UDP,端口号都只占16位,也就说其最大值也只有 65535。
那是不是说,如果使用TCP协议,在单台机器、单个IP地址时,并发连接数最大也只有65535呢?
Linux 协议栈,通过五元组来标志一个连接(即协议,源 IP、源端口、目的 IP、目的端口)
对客户端来说,每次发起TCP连接请求时,都需要分配一个空闲的本地端口,去连接远端的服务器
由于这个本地端口是独占的,所以客户端最多只能发起65535个连接
对服务器端来说,其通常监听在固定端口上等待客户端的连接
根据五元组结构,客户端的IP和端口都是可变的
如果不考虑IP地址分类以及资源限制
服务器端的理论最大连接数,可以达到2的48次方(IP为32位,端口号为16位),远大于65535
所以综合来看,客户端最大支持65535个连接,而服务器端可支持的连接数是海量的。
当然,由于Linux协议栈本身的性能,以及各种物理和软件的资源限制等
这么大的连接数,还是远远达不到的(实际上C10M就已经很难了)