linux:多路复用I/O

概念:

应用程序中需要同时处理多路输入输出流:
若采用阻塞模式,将得不到预期效果;
若采用非阻塞模式,对输入输出轮询,又太浪费CUP资源 资源;
若设置多进程,分别处理多跳数据通路,将产生新进程的同步和通信问题,使得程序变得复杂;
因此,采用多路复用I/O,基本思想:
1. 先构造一张有关描述符表,然后调用一个函数监控这个表,当这些文件描述符中的一个或者多个已经准备好进行I/O通信时,函数才返回,否则就阻塞。
2. 函数返回时告诉进程已经就绪的文件描述符,可进行I/O操作。

实现方法:
1. select();
2. poll();
3. epoll();

具体使用方法;

1. select();
int select(int maxfd, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);

maxfd: 所有监控的文件描述符中最大的+1;
read_fds/write_fds/except_fds: 想要 (读/写/异常通知) 的文件描述符集合;
timeout:超时设置

  • NULL: 一直阻塞,知道有fd就绪或者出错;
  • 0: 仅仅检测fds状态 ,然后立即返回;
  • 正整数: 预设的超时时间;

select()会一直阻塞,直到一下情况发生:

  • 有文件可读;
  • 有文件可写;
  • 超时;

文件描述符的操作: (使用宏实现)

void FD_SET(int fd, fd_set *fdset); //将fd添加到fdset文件描述符集合;
void FD_CLR(int fd, fd_set *fdset); //从fdset集合删除fd
void FD_ZERO(fd_set *fdset);    //清除fdset中所有的fd,一般用于初始化
int FD_ISSET(int fd, fd_set *fdset);    //判断fd是否存在于fdset集合中
2. poll()函数

与select类似,但接口不同。如下:

#include <poll.h>
int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);
返回值:准备就绪的描述符
若超时则返回0
错误返回-1

fdarray[]:与select不同的是,pollfd不是为每个状态(可读/可写/异常)都构建一个描述符集fdset,而是构造一个pollfd结构体数组,每个数组元素制定一个描述符编号和对其所关心的状态,这在pollfd结构体可看到,如下:

struct pollfd{
    int fd; //fd to checck,or <0 to ingnor,要检查的fd,小于0则忽略
    short events; //events of interest on fd 所关心的状态事件
    short revents; //events that occurred on fd,实际发生的事件
}

nfds: pollfd[]结构体数组的元素个数;
timeout
-1: 一直等待,直到已准备好(返回就绪的fd)或者捕捉到一个信号(返回-1,errno = EINTR,这里的EINTR在网络监听listen的描述符集中发生的时候,意思是有一个新的连接请求,而不是错误。因此,这时候需要特殊处理,判断errno?=EINTR,如果是,则不需要结束进程。这在并发服务器会用到。)
使用方法
要告诉内核我们要关心的事件的话,必须要将结构体中的events设置好。当发生事件时(不一定是我们关心的),内核就会自动填写revents项。其中events可填写的如下:
poll中events选项.jpg
前四行: 监测可读性;
中间三行:检测可写性;
后三行: 检测错误信息(由内核返回时设置,即使在events中没有设置,如果相应条件发生,也会自动填写到revents)。
- POLLHUP: 如果文件描述符挂断了,此时无法在向其写,但还是可以读的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MichaelJay2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值