调用操作系统的Se

调用操作系统的Se

         Httpd服务进阶知识-调用操作系统的Sendfile机制

                                                作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.不用 sendfile 的传统网络传输过程

  read(file, tmp_buf, len)
  write(socket, tmp_buf, len)   硬盘 >> kernel buffer >> user buffer >> kernel socket buffer >> 协议栈   一般网络应用通过读硬盘数据,写数据到 socket 来完成网络传输,底层执行过程:
    ()系统调用 read() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 执行拷贝,把文件数据从硬盘读到一个 kernel buffer 里。
    ()数据从 kernel buffer 拷贝到 user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode
    ()系统调用 write() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后把步骤2读到 user buffer 的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer和 socket 相关联。
    ()系统调用 write() 返回,产生一个上下文切换:从 kernel mode 切换到 user mode(第4次切换),然后DMA从 kernel buffer 拷贝数据到协议栈(第4次拷贝)
  上面4个步骤有4次上下文切换,有4次拷贝,如能减少切换次数和拷贝次数将会有效提升性能

二.用 sendfile() 来进行网络传输的过程

  sendfile(socket, file, len);

  硬盘 >> kernel buffer (快速拷贝到kernel socket buffer) >> 协议栈
  
  在kernel 2.0+ 版本中,系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能减少切换次数而且还能减少拷贝次数 
    ()系统调用sendfile()通过DMA把硬盘数据拷贝到kernel buffer,然后数据被kernel直接拷贝到另外一个与socket相关的kernel buffer。这里没有user mode和kernel mode之间的切换,在kernel中直接完成了从一个buffer到另一个buffer的拷贝
    ()DMA 把数据从 kernel buffer 直接拷贝给协议栈,没有切换,也不需要数据从user mode拷贝到kernel mode,因为数据就在kernel里
05-11 20:04