Linux高性能服务器编程:高级I/O函数

用于创建文件描述符的函数:pipe, dup, dup2

用于读写数据的函数:readv, writev, sendfile, mmap, munmap, splice, tee

用于控制I/O行为和属性的函数:fcntl

 

1.pipe函数

int pipe(int fd[2]);

pipe函数可用于创建一个管道,以实现进程间通信。

通过pipe函数创建的这两个文件描述符fd[0]和fd[1]分别构成管道的两端,往fd[1]写入的数据可以从fd[0]读出。

并且fd[0]只能用于从管道中读出数据,fd[1]从管道中写入数据。默认两个文件描述符都是阻塞的。

应用程序能往一个TCP连接中写入多少字节的数据,取决于对方的接收窗口的大小和本端的拥塞窗口的大小。而管道本身拥有一个容量限制,

规定了如果应用程序不将数据从管道读走的话,该管道最多能被写入多少字节的数据。默认大小为65536字节。

int socketpair(int domain, int type, int protocol, int fd[2]); //创建双向管道。

 

2. dup函数和dup2函数

int dup(int file_descriptor);

int dup2(int file_descriptor_one, int file_descriptor_two);

dup函数创建一个新的文件描述符,该新文件描述符和原有的文件描述符file_descriptor指向相同的文件、管道或者网络连接。

dup总是返回系统中最小的可用文件描述符。dup2返回第一个不小于file_descriptor_two的整数值。

 

3.readv函数和writev函数

ssize_t readv(int fd, const struct iovec* vector, int count);  //将数据从文件描述符读到分散的内存块中, 即分散读。

ssize_t writev(int fd, const struct iovec* vector, int count);  //将多块分散的内存数据一并写入文件描述符中,即集中写。

 

4. sendfile函数

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

ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);

in_fd是待读出内容的文件描述符,out_fd是待写入内容的文件描述符。offset参数指定从读入文件流的哪个位置开始读,如果为空,则使用读入文件流默认的起始位置。

count参数指定在文件描述符in_fd和out_fd之间传输的字节数。

in_fd必须是一个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道:而out_fd则必须是一个socket。

 

5.mmap函数和munmap函数

mmap函数用于申请一段内存空间,可以将这段内存作为进程间通信的共享内存,也可以将文件直接映射到其中。munmap释放该空间。

void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

void* munmap(void* start, size_t length);

flags参数:MAP_SHARED, 在进程中共享这段内存,对该内存的修改将反映到被映射的文件中,提供了进程间共享内存的POSIX方法。

 

6.splice函数

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

ssize_t splice(int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len, unsigned int flags);

fd_in, fd_out必须至少一个为管道描述符。返回移动字节的数量。0表示没有移动。

 

7.tee函数

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

ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);

 

8. fcntl函数

提供了对文件描述符的各种控制操作。

int fcntl(int fd, int cmd, ...);

将一个文件描述符设置为非阻塞的:

int setnonblocking(int fd) {
    int old_option = fcntl(fd, F_GETFL);
    int new_option = old_option | O_NONBLOCK;
    fcntl(fd, F_SETFL, new_option);
    return old_option;
}

 

posted @ 2020-02-27 16:01  c++11  阅读(216)  评论(0编辑  收藏  举报