系统调用
读文件时,应用层调用内核抽象层对外提供的接口即为系统调用,用户态切换到内核态
read 和 write
// 从文件(用fd表示)中读取len长度的内容,放到buffer中
read(fd, buffer, len);
// 把buffer中长度为len 的内容写入到socket中(用sockfd表示)
write(sockfd, buffer, len);
//注: read和write 应该是sys_read和sys_write的“包裹”函数,这里简化
1、从文件中读取内容,放到内核缓存区中(进入核心态)
2、从内核缓存区复制到用户缓冲区(read完成返回用户态)
3、发送数据,从用户缓存区复制到socket缓冲区(进入核心态)
4、网卡驱动异步发送数据(write完成返回用户态)
进入内核态两次,返回两次。
数据发生了三次复制,硬盘–>内核缓冲区–>用户缓冲区–>socket缓冲区
sendfile
不通过调用read和write,直接系统调用sendfile
sendfile(socket, file, len);
1、只进入内核态一次
2、只把位置和数据长度等信息从内核缓冲区复制到socket缓冲区,网卡驱动可以直接从内核缓冲区读取数据
zero copy
系统调用sendfile即为零拷贝
1、除了从硬盘读取数据时进行的DMA复制以外,没有任何其他复制
2、避免了数据不断地在用户态和核心态搬运,不需要CPU参与数据的复制,提高了系统性能