多路转接IO(select poll epoll )

1.IO类型

四种典型IO:阻塞,非阻塞,信号驱动,异步IO
阻塞:发起IO调用,如果IO就绪条件不满足,就一直等待
非阻塞:发起IO调用,如果IO就绪条件不满足,就立即报错返回。
信号驱动:定义IO信号的处理方式,然后可以处理其他的事情,等待收到IO就绪信号的时候,立即去处理IO(自己处理)
异步IO:IO顺序不确定,发起IO,然后将给系统处理,最后通过信号通知进程。(交给系统处理)
可读事件:一个描述符当前是否有数据可读
可写事件:一个描述符当前是否有可写入的数据
异常事件:一个描述符是否发生了某些异常

2.select
  1. 流程
    1.定义指定事件结构体集合,就绪事件有三种,初始化集合,将想要监控的事件描述符添加到集合中
    2.发起调用,将事件集合拷贝到内核,进行轮询遍历监控,将没有就绪的描述符集合移除,当有描述符就绪或者超时返回。
    3.程序员遍历判断,哪个描述符在哪个集合里,确定描述符就绪了哪个事件。

  2. 接口
    #include
    #include
    #include
    int select(int nfds, fd_set *readfds, fd_set *writefds,
    fd_set *exceptfds, struct timeval *timeout);
    nfds 所有集合中,描述符最大的数值+1
    set *readfds, 可读事件
    fd_set *writefds,可写事件
    fd_set *exceptfds, 异常事件
    struct timeval *timeout超时事件,最小单位是微秒
    返回值: <0 出错 =0 没有描述符就绪 >0 就绪描述符的个数
    void FD_CLR(int fd, fd_set *set); 清空集合
    int FD_ISSET(int fd, fd_set *set);判断某个描述符是否在集合
    void FD_SET(int fd, fd_set *set);将描述符添加到集合
    void FD_ZERO(fd_set *set);清空指定描述符集合

  3. 优缺点
    优点:跨平台,可移植性

    缺点:
    1.可以监控的描述符有最大上限,默认1024
    2.监控原理,对描述符集合进行轮询遍历,如果描述符增多,性能下降
    3.返回时移除未就绪的描述符,每次监控都需要重新添加描述符,重新拷贝到内核
    4.返回就绪的描述符,无法直接返回就绪描述符,还需要遍历判断哪个描述符在集合中

3.poll
  1. 流程
    1.定义事件结构体数组,将需要监控的描述符添加到数组
    2.发起监控,将数组中的数据添加到内核,轮询监控,有描述符就绪或者等待超时就返回,返回时如果没有就绪就描述符对应的revents为0,如果有就对应就绪事件
    3.遍历每个结点的revents,确定当前结点的描述符就绪了什么事件(例如可读/可写等)
    多路转接IO(select poll epoll )_第1张图片

  2. 接口
    #include
    int poll(struct pollfd fds, nfds_t nfds, int timeout);
    fds结构体
    struct pollfd {
    int fd; /
    file descriptor /
    short events; /
    requested events /
    short revents; /
    returned events */
    };
    描述符
    事件(读写等)
    实际就绪的事件,有就绪就把事件放进去,没有置0
    nfds: 事件结构体的数量
    超时等待时间:毫秒,>0 描述符个数 =0 监控超时 《0 监控出错

  3. 优缺点
    优点:
    1.和select类似,但是简化了描述符的事件集合
    2.每次监控,不需要重新定义结构体
    3.没有最大数量的限制,数组大小自己决定
    缺点:
    1.无法跨平台移植
    2.轮询遍历,也会随着描述符增加性能下降
    3.每次监控都需要将数组拷贝到内核监控
    4.返回的结构体也需要遍历来确定哪个描述符就绪了哪个事件。

4.epoll
  1. 流程
    1.定义eventpoll结构体
    2.对需要监控的事件描述符结构体,将描述符添加到内核eventpoll结构体中
    3.开始监控,有描述符就绪或者超时返回

  2. 接口
    1.int epoll_create(int size)
    返回值:操作句柄
    参数:描述符的最大数量(大于0即可)
    2.int epoll_ctl(int epfd, int op, int fd , struct epoll_event* event)
    epfd : epoll操作句柄
    op : 对描述符的操作
    event:监控描述符对应的事件结构体信息
    在这里插入图片描述
    3.nt epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
    epfd; epoll操作句柄
    evs: epoll_event描述符结构体数组的首地址,获取描述符对应的事件结构体
    maxevents:防止越界
    timeout:超时等待事件 毫秒

3.优缺点
优点:
1.监控的描述符没有上线
2.描述符信息只向内核拷贝一次
3.采用异步阻塞,性能不会下降
4.所有的就绪事件都在数组里,没有无效遍历
缺点:
无法跨平台,超时精确到毫秒

水平触发:
只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,
当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知
边缘触发:(新数据到来才写入)
当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,
当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知

你可能感兴趣的:(Linux操作系统)