当前位置: 技术问答>linux和unix
有谁知道zero copy是怎么回事吗?
来源: 互联网 发布时间:2015-01-16
本文导语: 如提,谢谢 | 具体参见: http://www.zdnet.com.cn/developer/code/story/0,2000081534,39031083,00.htm sendfile()的威力在于,它为大家提供了一种访问当前不断膨胀的Linux网络堆栈的机制。这种机制叫做“零拷贝(zero-...
如提,谢谢
|
具体参见:
http://www.zdnet.com.cn/developer/code/story/0,2000081534,39031083,00.htm
sendfile()的威力在于,它为大家提供了一种访问当前不断膨胀的Linux网络堆栈的机制。这种机制叫做“零拷贝(zero-copy)”,这种机制可以把“传输控制协议(TCP)”框架直接的从主机存储器中传送到网卡的缓存块(network card buffers)中去。为了更好的理解“零拷贝(zero-copy)”以及sendfile(),让我们回忆一下以前我们在传送文件时所需要执行的那些步骤。首先,一块在用户机器存储器内用于数据缓冲的位置先被确定了下来。然后,我们必须使用read()这条系统呼叫来把数据从文件中拷贝到前边已经准备好的那个缓冲区中去。(在通常的情况下,这个操做会把数据从磁盘上拷贝到操作系统的高速缓冲存储器中去,然后才会把数据从高速缓冲存储器中拷贝至用户空间中去,这种过程就是所谓的“上下文切换”。)在完成了上述的那些步骤之后,我们得使用write()系统呼叫来将缓冲区中的内容发送到网络上去,程序段如下所示:
intout_fd, intin_fd;
char buffer[BUFLEN];
…
/* unsubstantial code skipped for clarity */
…
read(in_fd, buffer, BUFLEN); /* syscall, make context switch */
write(out_fd, buffer, BUFLEN); /* syscall, make context switch */
操作系统核心不得不把所有的数据至少都拷贝两次:先是从核心空间到用户空间的拷贝,然后还得再从用户空间拷贝回核心空间。每一次操做都需要上下文切换(context-switch)的这个步骤,其中包含了许多复杂的高度占用CPU的操作。系统自带的工具vmstat能够用来在绝大多数UNIX以及与其类似的操作系统上显示当前的“上下文切换(context-switch)”速率。请看叫做“CS”的那一栏,有相当一部分的上下文切换是发生在取样期间的。用不同类型的方式进行装载可以让使用者清楚的看到使用这些参数进行装载时的不同效果。
在有了sendfile()零拷贝(zero-copy)之后,如果可能的话,通过使用直接存储器访问(Direct Memory Access)的硬件设备,数据从磁盘读取到操作系统高速缓冲存储器中会变得非常之迅速。而TLB高速缓冲存储器则被完整无缺的放在那里,没有充斥任何有关数据传输的文件。应用软件在使用sendfile() primitive的时候会有很高的性能表现,这是因为系统呼叫没有直接的指向存储器,因此,就提高了传输数据的性能。通常来说,要被传输的数据都是从系统缓冲存储器中直接读取的,其间并没有进行上下文切换的操作,也没有垃圾数据占据高速缓冲存储器。因此,在服务器应用程序中使用sendfile()能够显著的减少对CPU的占用。
http://www.zdnet.com.cn/developer/code/story/0,2000081534,39031083,00.htm
sendfile()的威力在于,它为大家提供了一种访问当前不断膨胀的Linux网络堆栈的机制。这种机制叫做“零拷贝(zero-copy)”,这种机制可以把“传输控制协议(TCP)”框架直接的从主机存储器中传送到网卡的缓存块(network card buffers)中去。为了更好的理解“零拷贝(zero-copy)”以及sendfile(),让我们回忆一下以前我们在传送文件时所需要执行的那些步骤。首先,一块在用户机器存储器内用于数据缓冲的位置先被确定了下来。然后,我们必须使用read()这条系统呼叫来把数据从文件中拷贝到前边已经准备好的那个缓冲区中去。(在通常的情况下,这个操做会把数据从磁盘上拷贝到操作系统的高速缓冲存储器中去,然后才会把数据从高速缓冲存储器中拷贝至用户空间中去,这种过程就是所谓的“上下文切换”。)在完成了上述的那些步骤之后,我们得使用write()系统呼叫来将缓冲区中的内容发送到网络上去,程序段如下所示:
intout_fd, intin_fd;
char buffer[BUFLEN];
…
/* unsubstantial code skipped for clarity */
…
read(in_fd, buffer, BUFLEN); /* syscall, make context switch */
write(out_fd, buffer, BUFLEN); /* syscall, make context switch */
操作系统核心不得不把所有的数据至少都拷贝两次:先是从核心空间到用户空间的拷贝,然后还得再从用户空间拷贝回核心空间。每一次操做都需要上下文切换(context-switch)的这个步骤,其中包含了许多复杂的高度占用CPU的操作。系统自带的工具vmstat能够用来在绝大多数UNIX以及与其类似的操作系统上显示当前的“上下文切换(context-switch)”速率。请看叫做“CS”的那一栏,有相当一部分的上下文切换是发生在取样期间的。用不同类型的方式进行装载可以让使用者清楚的看到使用这些参数进行装载时的不同效果。
在有了sendfile()零拷贝(zero-copy)之后,如果可能的话,通过使用直接存储器访问(Direct Memory Access)的硬件设备,数据从磁盘读取到操作系统高速缓冲存储器中会变得非常之迅速。而TLB高速缓冲存储器则被完整无缺的放在那里,没有充斥任何有关数据传输的文件。应用软件在使用sendfile() primitive的时候会有很高的性能表现,这是因为系统呼叫没有直接的指向存储器,因此,就提高了传输数据的性能。通常来说,要被传输的数据都是从系统缓冲存储器中直接读取的,其间并没有进行上下文切换的操作,也没有垃圾数据占据高速缓冲存储器。因此,在服务器应用程序中使用sendfile()能够显著的减少对CPU的占用。