文章目录
  1. readv与writev函数
  2. sendfile函数
  3. mmap与munmap函数
  4. splice函数
  5. tee函数

readv与writev函数

readv函数将数据从文件描述符读到分散的内存块,即分散读;writev函数将多块分散的内存数据一并写入文件描述符,即集中写。

1
2
3
4
5
6
7
8
/*
引用方式: #include <sys/uio.h>
cnt: vec数组的长度
返回读出/写入的字节数: 成功 || 返回-1并设置errno: 失败
*/
sszize_t readv(int fd, const struct iovec * vec, int cnt);

sszize_t writev(int fd, const struct iovec * vec, int cnt);

根据HTTP响应报文格式,状态行、多个头部字段、1个空行与文档内容,文档内容通常与前面的内容是分开的;因此,可以使用writev函数将它们同时写出。

sendfile函数

sendfile函数在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了内核缓冲区与用户缓冲区之间的数据拷贝,效率很高,这称为零拷贝。

1
2
3
4
5
6
7
/*
引用方式: #include <sys/sendfile.h>
offset: 指定从读入文件流的哪个位置开始读; 为空则从读入文件流默认的起始位置开始
cnt: 指定传输的字节数
返回传输的字节数: 成功 || 返回-1并设置errno: 失败
*/
ssize_t sendfile(int out, int fd, off_t * offset, size_t cnt);

man 2 sendfile明确指出:fd必须是支持mmap函数的文件描述符,必须指向真实的文件,不能是socket或管道;而out必须是一个socket。

mmap与munmap函数

mmap函数用于申请一段内存空间,这段内存可以用于进程间通信,也可以用于映射文件。munmap释放由mmap创建的内存空间。

1
2
3
4
5
6
7
8
9
/*
引用方式: #include <sys/mman.h>
start: 指定分配的内存的起始地址; 若设置为NULL则由系统自动分配
prot: 设置内存段的访问权限; PROT_READ: 可读 || PROT_WRITE: 可写 ||PROT_EXEC: 可执行 || PROT_NONE: 内存不可访问; prot可取几个值的按位或
flags: 控制内存被修改后程序的行为, 详见下表
fd: 被映射文件的文件描述符(一般由open获得)
返回目标内存区域的指针: 成功 || 返回MAP_FAILED((void *)-1)并设置errno: 失败
*/
void * mmap(void * start, size_t len, int prot, int flags, int fd, off_t offset);

 

flags参数取某些值的按位或(除了MAR_SHARED与MAR_PRIVATE互斥外)。

1
2
3
4
5
/*
引用方式: #include <sys/mman.h>
返回0: 成功 || 返回-1并设置errno: 失败
*/
int munmap(void * start, size_t len);

splice函数

splice函数用于在两个文件描述符之间移动数据,也是零拷贝操作。

1
2
3
4
5
6
7
8
9
10
11
/*
引用方式: #include <fcntl.h>
in: 待输入数据的文件描述符
off_in: 在in不是一个管道文件描述符时, 指定从输入数据流的何处偏移开始读取数据, 置NULL表示从数据流的当前偏移开始读入
out: 接收管道输出数据的文件描述符
off_out: 在out不是一个管道文件描述符时, 指定从输出数据流的何处偏移开始接收数据, 置NULL表示从数据流的当前偏移开始接收
len: 传输数据的长度上限
flags: 控制数据如何移动, 详见下表
返回传输字节长度(可能为0): 成功 || 返回-1并设置errno: 失败
*/
ssize_t splice(int in, loff_t * off_in, int out, loff_t * off_out, size_t len, unsigned int flags);

文件描述符in与out必须至少有一个是管道文件描述符。

tee函数

tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作。

1
2
3
4
5
/*
引用方式: #include <fcntl.h>
返回传输字节长度(可能为0): 成功 || 返回-1并设置errno: 失败
*/
ssize_t tee(int in, int out, size_t len, unsigned int flags);