1 把磁盘文件读入内核缓冲区
2 从内核缓冲区读到内存
3 处理(静态资源不需处理)
4 发送到网卡的内核缓冲区(发送缓存)
5 网卡发送数据
数据从第一步中的内核缓冲区到第四步的内核缓冲区白白绕了一个圈,没有任何变化浪费了时间
而sendfile系统调用就是来解决这个问题的。sendfile省略了上面的 2、3步,磁盘文件被直接发送到了网卡的内存缓冲区,减少了数据复制和内核态切换的开销 。
现在流行的 web 服务器里面都提供 sendfile 选项用来提高服务器性能,那到底 sendfile 是什么,怎么影响性能的呢?sendfile 实际上是 Linux 2.0+ 以后的推出的一个系统调用,web 服务器可以通过调整自身的配置来决定是否利用 sendfile 这个系统调用。先来看一下不用 sendfile 的传统网络传输过程:
read(file, tmp_buf, len);
write(socket, tmp_buf, len);硬盘 >> kernel buffer >> user buffer >> kernel socket buffer >> 协议栈
一般来说一个网络应用是通过读硬盘数据,然后写数据到 socket 来完成网络传输的。上面2行用代码解释了这一点,不过上面2行简单的代码掩盖了底层的很多操作。来看看底层是怎么执行上面2行代码的:
1、系统调用 read() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 执行拷贝,把文件数据从硬盘读到一个 kernel buffer 里。
2、数据从 kernel buffer 拷贝到 user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode。
3、系统调用 write() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后把步骤2读到 user buffer 的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer 和 socket 相关联。
4、系统调用 write() 返回,产生一个上下文切换:从 kernel mode 切换到 user mode(第4次切换了),然后 DMA 从 kernel buffer 拷贝数据到协议栈(第4次拷贝了)。
上面4个步骤有4次上下文切换,有4次拷贝,我们发现如果能减少切换次数和拷贝次数将会有效提升性能。在kernel 2.0+ 版本中,系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能减少切换次数而且还能减少拷贝次数。
再来看一下用 sendfile() 来进行网络传输的过程:
sendfile(socket, file, len);
硬盘 >> kernel buffer (快速拷贝到kernel socket buffer) >> 协议栈
1、系统调用 sendfile() 通过 DMA 把硬盘数据拷贝到 kernel buffer,然后数据被 kernel 直接拷贝到另外一个与 socket 相关的 kernel buffer。这里没有 user mode 和 kernel mode 之间的切换,在 kernel 中直接完成了从一个 buffer 到另一个 buffer 的拷贝。
2、DMA 把数据从 kernel buffer 直接拷贝给协议栈,没有切换,也不需要数据从 user mode 拷贝到 kernel mode,因为数据就在 kernel 里。
步骤减少了,切换减少了,拷贝减少了,自然性能就提升了。这就是为什么说在 Nginx 配置文件里打开 sendfile on 选项能提高 web serve r性能的原因。
相关推荐
在Linux和FreeBSD上,它直接调用底层的sendfile系统调用;而在不支持sendfile的系统上,如Windows,它会模拟类似的功能,例如通过内存映射文件和write系统调用来达到类似的效果。 在Haskell编程语言中,"simple-...
《Linux系统函数调用大全》是一本深入探讨Linux操作系统中函数调用的宝贵资源,它涵盖了广泛的主题,旨在帮助开发者和系统管理员更好地理解和利用Linux内核功能。这本书以PDF格式提供,是学习和查阅Linux系统编程的...
sendfile系统调用是Linux内核中的一个特性,允许内核直接将文件内容从文件系统的缓存复制到网络发送缓冲区,从而减少了用户空间到内核空间的数据拷贝,提高了数据传输的效率。在TCP编程中,通常会用到read和write...
`sendfile` 是一个在操作系统层面用于高效传输文件的系统调用,主要应用于网络服务器,如HTTP服务器,用于将文件内容直接从磁盘传递到网络套接字,避免了用户空间到内核空间的数据拷贝,提高了文件传输的效率。...
总结来说,Arm Linux系统调用流程包括用户空间调用系统调用接口,处理器切换到系统模式,查找并执行相应的系统调用处理函数,执行完毕后返回用户空间。这一过程涉及了处理器模式切换、中断处理、系统调用表、上下文...
### Linux系统调用错误代码(Errno)详解 在Linux操作系统中,系统调用是应用程序与内核交互的重要方式之一。当系统调用失败时,通常会返回一个负数,并将具体的错误码存储在全局变量`errno`中。了解这些错误码对于...
在Linux操作系统中,文件传输是一种常见的任务,而`Linux file socket`是实现这一功能的一种机制。Socket编程在Linux中扮演着重要角色,不仅用于网络通信,也可以用来在本地进行进程间通信(IPC)。本教程将深入讲解...
Linux虚拟文件系统(Virtual File System,VFS)是一个抽象层,它为不同的文件系统提供了一个统一的接口。这使得Linux可以支持多种不同的文件系统类型,如ext2、ext3、ext4、XFS、Btrfs等。在VFS之下,每种具体的...
为了解决这个问题,Linux引入了`sendfile()`系统调用,它允许直接将磁盘文件内容传输到套接字,避免了数据在用户空间和内核空间之间的多次拷贝,极大地提高了文件传输的效率。`sendfile()`的工作原理是在内核内部...
在《Linux内核编程经验实践》这篇文章中,作者分享了自己在Linux内核开发方面的经验和心得,并着重介绍了如何编译内核以及如何添加自定义系统调用等内容。本文将深入解析文中的关键知识点,帮助读者更好地理解Linux...
Video_Live_Stream是在Linux系统下基于python调用ffmpeg实现的简易推流工具,基本功能如下: * 读取播放列表,按列表顺序循环推流视频至rtmp服务器。 * 添加了`bilibili直播间弹幕模块`,可接收及发送弹幕。 * 可...
sendfile系统调用在Unix-like操作系统(如Linux)中广泛使用,它允许内核直接将一个文件的数据拷贝到另一个文件描述符,而无需通过用户空间进行数据拷贝。这一特性减少了上下文切换和内存拷贝的开销,对于大文件传输...
3. 利用sendfile系统调用直接将文件内容从一个文件描述符传输到另一个文件描述符(通常是从文件到socket),减少了复制操作。 4. 文件租赁(Lease)机制,确保文件在操作过程中不被其他进程修改,从而避免了错误的...
这个“Linux系统编程课件”涵盖了多个关键主题,包括File I/O(输入/输出)、Files and Directories(文件和目录)、IPC(Inter-Process Communication,进程间通信)、Process Control(进程控制)、Pthread(线程...
- **工作流程**:sendfile()系统调用更进一步优化了数据传输,如图1所示,它直接从文件的内核缓冲区拷贝到socket的内核缓冲区,然后由DMA将数据送至协议引擎,省去了用户空间的参与。即使在数据传输过程中文件被...
在Linux系统中,零拷贝主要通过内存映射、sendfile系统调用等方式实现。 本文提出了一种名为PF-DMA(Packet Filtering Direct Memory Access)的新型零拷贝报文捕获技术,它是在Linux系统环境下实现的。PF-DMA通过...
2. **文件系统**:Linux采用Hierarchical File System(HFS),以树形结构组织文件。每个文件都有唯一标识符(inode),记录其元数据如权限、大小、创建时间等。目录被视为特殊类型的文件,可以包含其他文件或目录。...
3. 文件系统:Linux采用的是Hierarchical File System(HFS),以树形结构组织文件。 二、Linux文件系统操作 1. 文件和目录操作:包括创建、删除、移动、复制、重命名文件及目录。 2. 权限管理:Linux的文件权限...