Linux系统编程--第二章 之 IO多路复用

原因:应用程序通常需要在多于一个文件描述符上阻塞,在不使用线程,尤其是独立处理每一个文件的情况下,进程无法在多个文件描述符上同时阻塞。如果读一个未准备好的文件描述符,进程会被阻塞,不能再操作其他文件,可能阻塞只有几秒,但是应用无响应也会造成不好的用户体验。

解决:非阻塞IO。缺点:进程需要不断的发起IO请求,直到响应的fd准备好,其次进程要是可以睡眠,处理器运行效率更高,等到一个或多个文件描述符可以进行IO操作时再唤醒进程。

于是产生了IO多路复用:

1、IO多路复用允许应用在多个文件描述符上同时阻塞,并在某个文件描述符可以读写的时候收到通知。

2、IO多路复用设计原则:

             1、当任何文件描述符准备好I/O的时候告诉通知进程;2、在一个或者多个文件描述符就绪之前时钟处于睡眠状态;3、哪个fd准备好了;4、在不阻塞的情况下,处理所有IO就绪文件描述符;5、返回第一步,重新开始。

 

3、I/O多路复用方案:

3.1:select()系统调用:同步IO多路复用机制

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

FD_CLR(int fd, fd_set *set);//从指定集合中移除一个文件描述符
FD_ISSET(int fd, fd_set *set);//确认一个文件描述符是否在集合中
FD_SET(int fd, fd_set *set);//向指定集合添加文件描述符
FD_ZERO(fd_set *set);//清除指定集合中全部的文件描述符,select调用之前需要使用该宏

监测三类文件描述符:                 当指定集合为NULL时,select不对此类进行监测。
readfds集合:确认其中是否有可读数据;
writefds集合:确认其中是否有一个写操作做可以无阻塞完成。
exceptefds:确认其中是否有异常发生或者出现带外数据。
timeout:当没有文件描述符处于就绪状态时,select将在timeout时间后返回。期间Unix系统处于未定义状态

n:最大文件描述符加一

select:在指定文件描述符准备好IO之前或者设定的时间到之前,select调用就会阻塞。【主动阻塞】

select返回值:所有三个集合中文件描述符的个数。

 

4、poll系统调用

#include <sys/poll.h>
int poll (struct pollfd *fds, unsigned int nfds, int timeout);
/*传递一个pollfd结构体类型的数组, 数组每个元素监视一个文件描述符, */
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};

 

5、poll和select

 

6、epoll:

poll() 和 select() 每次调用时都需要所有被监听的文件描述符,内核必须遍历所有被监听的文件描述符,当这个表变得很大的时候,每次调用就成为了明显的瓶颈。

epoll() 把监听注册从 实际的监听中分离出来。

创建一个epoll实例:

/*
*  参数:size参数表示需要监听的描述符个数。一个大概的数字
*  返回:一个与创建的实例相关的描述符epfd,该描述符与真正的普通文件无关,用于后续系统调用
*/
int epoll_create (int size);

控制epoll   :向指定的epfd中添加或删除需要监测文件描述符,并指定监听的事件

/*
*  输入:
*      op:操作类型:EPOLL_CTL_ADD、EPOLL_CTL_DEL、EPOLL_CTL_MOD
*      event.events:给定文件描述符上的监听事件    event.data:
*
*/
int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);

struct epoll_event{
    __u32 events;//指定监测fd上的哪种触发事件
    union{void *ptr; int fd; __u32 u32; __u64 u64;}data;//供用户使用,一般初始化为描述符fd,最后可以用于检查该结构体代表的事件属于那个fd
};

等待epoll事件:

int epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout);

函数说明:

     返回:成功时返回就绪的文件描述符的个数,失败时返回-1并设置errno

     timeout:指定epoll的超时时间,单位是毫秒。当timeout为-1是,epoll_wait调用将永远阻塞,直到某个事件发生。当timeout为0时,epoll_wait调用将立即返回。

     maxevents:指定最多监听多少个事件

     events:检测到事件,将所有就绪的事件从内核事件表中复制到它的第二个参数events指向的数组中。用户根据之前设置的data字段可以判断该结构代表触发了那个文件描述上的事件。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值