小林图解系统网络系统
Linux接受网络包的流程:
当网卡接收到网络包后,会通过DMA技术,将网络包放到Ring Buffer,这是一个环形缓冲区,然后应该告知操作系统网络包已经到达了。每个I/O设备都有自己的DMA控制器。
最简单的一种方式就是触发中断,但是存在一个问题就是网络包很多时会频繁触发中断,影响系统的性能;因此Linux内核采用了NAPI机制,即网卡先采用硬件中断处理函数,中断处理函数处理完需要暂时屏蔽硬件中断,唤醒数据接收的服务程序,然后服务程序采用poll的方法软中断来轮询数据,直到没有数据才回复硬中断,这样一次中断可以处理多个网络包。
软中断处理流程:
- 从Ring Buffer中拷贝数据到内核struct sk_buff缓冲区,从而作为网络包交给网络协议栈逐层处理;
- 进入网络接口层检测报文合理性,接着交给网络层,传输层依次检测,最后调用Socket端口把数据拷贝到Socket的接受缓冲区。
零拷贝:
有DMA技术后的I/O操作,在进行I/O设备和内存的数据传输的时候,数据的搬运工作全部交给DMA控制器。
read和write实现时内核中发生的过程:共发生了2次系统调用,4次用户态和内核态的上下文切换,每次进行系统调用时,都需要从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。
磁盘到内核态拷贝的过程是DMA实现的,内核态到用户态的拷贝是通过CPU实现的;
想要减少上下文切换的次数,就要减少系统调用的次数。
mmap()系统调用可以直接将内核缓冲区的数据映射到用户空间,这样内核态和用户态之间就不需要数据拷贝,减少了一次数据拷贝,但是还是需要2个系统调用,4次上下文切换。
而sendfile系统调用函数,只需要一次系统调用,2次上下文切换,3次数据拷贝
而如果网卡支持scatter-gather属性,还可以减少一次数据拷贝,只需要两次数据拷贝。
这也就是所谓的零拷贝,没有在内存层面拷贝数据,全程都是通过DMA来传输数据,CPU没有参与。
PageCache技术:
将最近被访问的数据拷贝到PageCache,可以提高读写的速度。有点类似读取磁盘到内存中,相当于缓存,内核缓冲区。这种方式也叫缓存I/O,适合传输小文件;
此外,其还有预读功能,也就是读取磁盘文件时多读一部分数据到PageCache中,这样下次如果访问到就不用到磁盘找了。
但是这个技术不适合大文件传输,大文件传输应该用异步I/O的方式。因为PageCache可能被大文件占用,小的热点文件无法利用PageCache,这样大文件的缓存命中率不高,而经过PageCache需要多一次拷贝的开销。
异步I/O,也可以说是直接I/O,可以直接将磁盘缓冲区的数据拷贝到用户缓冲区,没有PageCache
Linux命令
通常以4个指标衡量网络的性能:带宽,延时,吞吐量,PPS(Packet Per Second)。此外,还有网络可用性,并发连接数,丢包率,重传率等性能指标
- 带宽:链路的最大传输速率,单位是(b/s)
- 延时:表示数据包发送后,收到对端相应,所需要的时间延迟
- 吞吐量:单位时间成功传输的数据量