_ct##总览
散布/聚集I/O:I/O在单次调用中同时对多个缓冲区做读取或者写入操作,适合于聚集多个不同数据结构进行统一的I/O操作。
epoll:poll()和select()的改进版,在一个程序需要处理数百个文件描述符的时候很有用。
内存映射I/O:将文件映射到内存,可以用简单的内存管理方式来处理文件,适合有特殊要求的I/O。
文件I/O提示:语序进程将文件I/O使用上的一些提示信息提供给内核;能提升I/O性能。
异步I/O:允许进程发出多个I/O请求并且不用等待其完成;适用于不适用线程的情况下处理重负载I/O操作。
散布/聚集 I/O
可以把单个数据流的内容写到多个缓冲区或者把单个数据流读到多个缓冲区。因为数据被散布到一个缓冲区向量,或者从一个缓冲区向量聚集。这种方法的另一个名字叫向量I/O。第二章标准读写系统调用叫线性I/O。
优点:
(1)效率:单个向量I/O操作代替多个线性I/O;
(2)性能:使用系统调用次数降低,由于内部优化,向量I/O比线性I/O提供更好的性能。
(3)原子性:执行单个向量I/O避免了与其他进程交叉的风险。
readv()和writev()
#include <sys/uio.h>
/* 从fd读取count个segment到iov描述缓冲区中 */
ssize_t readv(int fd, const struct iovec *iov, int count);
/*
* 从iov描述缓冲区中读取count个segment到fd中
*/
ssize_t writev(int fd, const struct iovec, int count;);
每个iovec结构体描述一个独立的缓冲区,我们称其为段。一组segment集合我们成为向量。每个段秒速读写的缓冲区的地址和长度。readv在处理下一个缓冲区的时候会填满当前缓冲区的iov_len个字节。writev在处理下一个缓冲区是先把当前缓冲区的iov_len个字节全部输出。从iov[0]一直到iov[count - 1]
#include <sys/uio.h>
struct iovec
{
void *iov_base;
size_t iov_len;
};
如果成功分别返回读写的字节数,返回值应该等于iov_len的和,出错返回-1,设置errno。
iov_len必须的和大于SSIZE_MAX则不做处理返回-1,errno设置为EINVAL。
count必须大于0小于等于IOV_MAX。
Event poll接口
在poll()和select()每次调用时都需要所有被监听的文件描述符。内核必须遍历所有被监视的文件描述符。这个表变得很大的时候每次调用遍历就成为了明显的瓶颈。
epoll把监听注册从实际监听中分离出来,从而解决这个问题。一个系统调用初始化一个epoll上下文,另一个从上下文中加入或删除需要监听的文件描述符,第三个执行真正的事件等待。
创建一个新的epoll实例
#include <sys/poll.h>
int epoll_create(int size);
雕用成功创建一个epoll实例返回与该实例相关的文件描述符。size参数是需要监听的文件描述符数目。出错是返回-1,设置errno。
int epfd;
epfd = epoll_create(100);
if(epfd < 0)
perror("epoll_create");
控制epoll
epoll_ctl()可以向指定的epoll上下文中加入或删除文件描述符
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll_event结构体
struct epoll_event
{
__u32 events;
union
{
void *ptr;
int fd