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


高级I/O函数
 
pipe函数
 
pipe函数用于创建一个管道,实现进程间的通信。
 
#include <unistd.h>
 
int pipe(int pipefd[2]);
 
通过pipe函数创建的文件描述符fd[0]和fd[1]分别构成管道的两端,往fd[1]写入的数据可以从fd[0]读出,不能反过来。管道内部传输的数据时字节流,和TCP字节流概念相同,但有区别,管道本身拥有一个容量限制,它规定如果应用程序不将数据从管道读走的话,该管道最多能被写入多少字节的数据。管道容量阿东小默认是65536字节,可以用fcntl函数来修改管道容量。
 
此外,socket基础API中有一个socketpair函数,能够方便创建双向管道。
 
#include<sys/types.h>        /* See NOTES*/
 
#include<sys/socket.h>
 
intsocketpair(int domain, int type, int protocol, int sv[2]);
 
这里domain只能使用UNIX本地域协议族AF_UNIX,因为我们仅能在本地使用这个双向管道。
 
dup函数和dup2函数
 
#include <unistd.h>
 
int dup(int oldfd);
 
int dup2(int oldfd, int newfd);
 
dup函数创建一个新的文件描述符,该新的文件描述符和原有的文件描述符file_descriptor指向相同的文件、管道或网络连接。并且dup返回的文件描述符总是取系统当前可用的最小整数值。Dup2和dup类型,不过它将返回第一个不小于newfd的整数值。dup和dup2系统调用失败时返回-1并设置errno。
 
通过dup和dup2创建的文件描述符并不继承原文件描述符的属性。
 
readv函数和writev函数
 
readv函数将数据从文件描述符督导分散的内存块中,即分散读。Writev函数则将多块分散的内存数据一并写入文件描述符中,即集中写。定义如下:
 
#include <sys/uio.h>
 
ssize_t readv(int fd, const struct iovec*iov, int iovcnt);
 
ssize_t writev(int fd, const struct iovec*iov, int iovcnt);
 
fd是文件描述符,iov是iovec结构数组,该结构体描述一块内存区,iovcnt参数是数组的长度。
 
sendfile函数
 
sendfile函数在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了内核缓冲区和用户缓冲区之间的数据拷贝,效率高,这被称为零拷贝。
 
#include <sys/sendfile.h>
 
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之间传输的字节数。
 
mmap函数和munmap函数
 
mmap函数用于申请一段内存空间。我们可以将这段内存作为进程通信的共享内存,也可以将文件直接映射到其中。Munmap函数则释放由mmap创建的这段内存空间。定义如下:
 
#include <sys/mman.h>
 
void *mmap(void *addr, size_t length, intprot, int flags, int fd, off_t offset);
 
int munmap(void *addr, size_t length);
 
其中,start参数允许用于使用某个特定的地址作为这段内存的起始地址。如果被设置成NULL,则系统自动分配一个地址。Length参数指定内存段的长度。Port参数用来设置内存段的访问权限,flag参数控制内存段被修改后程序的行为。Fd参数是被映射文件对应的文件描述符。Mmap函数成功时返回指向目标内存区域的指针,失败则返回MAP_FAILED,并设置errno。
 
splice函数
 
#include <fcntl.h>
 
ssize_t splice(int fd_in, loff_t *off_in,int fd_out, loff_t *off_out, size_t len, unsigned int flags);
 
用来控制两个文件描述符之间的数据移动,也是零拷贝操作。Flag参数控制数据流如何移动。
 
tee函数
 
tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作。Tee函数的原型如下:
 
#define _GNU_SOURCE        /* See feature_test_macros(7) */
 
#include <fcntl.h>
 
ssize_t tee(int fd_in, int fd_out, size_tlen, unsigned int flags);
 
fcntl函数
 
fcntl函数提供了对文件描述符的各种控制操作。另外一个常见的控制文件描述符属性和行为的系统调用时ioctl,而且ioctl比fcntl能够执行更多的控制。

《Unix/Linux编程实践教程》之Shell编程一

《Unix/Linux编程实践教程》之Shell编程二

《Unix/Linux编程实践教程》之管道

Unix/Linux编程实践教程【高清PDF中文版+附录光盘+代码】:

本文永久更新链接地址:

相关内容