多路IO复用(Linux)

一、介绍

多路IO复用,是通过系统底层对描述符事件的检测,通过描述符集合返回,通过描述符集合实现对单一句柄操作

多路IO复用有三种:

(1)select

(2)poll

(3)epoll

对比:

特点selectpollepoll
句柄个数

32位 <1024

64位 <2048

无限制无限制
平台POSIXLinuxLinux
监听方式轮询轮询事件通知

触发方式

水平触发水平触发

边缘        ET

水平        LT

效率

(fd数量上升)

线性下降线性下降无变化
消息传递方式内核拷贝至用户空间内核拷贝至用户空间内核与用户空间共用一块内存

二、函数接口

1、select

头文件<sys/select.h>

1、阻塞检测
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
返回值:
    超时:0
    成功:返回触发个数
    失败:-1
参数:
    nfds:描述符上限,即所有文件描述符的最大值加1
	readfds 只读描述符集
	writefds 只写描述符集
	exceptfds 异常描述符集    
    timeout:检测超时,NULL表示一直不超时

2、添加描述符
void FD_SET(int fd, fd_set *set);

3、删除描述符
void FD_CLR(int fd, fd_set *set);

4、判断描述符是否在集合
int  FD_ISSET(int fd, fd_set *set);

5、清空集合
void FD_ZERO(fd_set *set);

2、poll

头文件<poll.h>

1、阻塞等待
int poll(struct poll_fd *fds, nfds_t nfds, int timeout);
返回值:
    成功:返回描述符集合个数
    超时:0
    失败:-1
参数:
    fds:描述符集合数组
    nfds:fds数组长度
    timeout:超时,单位ms

        struct pollfd {
            int   fd;         /* file descriptor */
            short events;     /* requested events */
            short revents;    /* returned events */
        };

3、epoll

头文件<sys/epoll.h>

1、创建
int epoll_create(int size);
int epoll_create1(int flags);
返回值:
    成功:返回epoll描述符(句柄)
    失败:-1
参数:
    size:告诉内核一个管理句柄的个数估值,内核版本2.6.8之后,该参数被忽略
    flags:设置为0与epoll_create无差别

2、控制
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
返回值:
    成功:0
    失败:-1或者错误号
参数:
    epfd:epoll的描述符
    op:选项
        EPOLL_CTL_ADD:添加
        EPOLL_CTL_MOD:修改
        EPOLL_CTL_DEL:删除
    fd:被操作的描述符
    event:描述符fd的事件
        typedef union epoll_data {
            void        *ptr;
            int          fd;
            uint32_t     u32;
            uint64_t     u64;
        } epoll_data_t;

        struct epoll_event {
            uint32_t  events;      /* Epoll events */
            epoll_data_t data;        /* User data variable */
        };
        events:
            EPOLLIN:读触发
            EPOLLOUT:写触法
            EPOLLET:边缘触发,默认是水平触发
            EPOLLRDHUP:流套接字close或shutdown写,在ET模式比较有用
            EPOLLERR:出错
            EPOLLPRI:紧急数据可读
            EPOLLHUP:挂起,EPOLLERR和EPOLLHUP始终由epoll_wait监听,不需要用户设置

       
3、事件等待     
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask); 
返回值:
    成功:返回触发句柄个数,0为超时
    失败:-1或者错误号
参数:
    epfd:epoll句柄
    events:触发句柄的事件载体,通常为一个struct epoll_event数组
    maxevents:处理最大个数
    timeout:超时时间
    sigmask:信号屏蔽掩码    

以下两种操作等价
(操作1)
ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);   
(操作2)
sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = epoll_wait(epfd, &events, maxevents, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);

sigmask=NULL时,两函数等价       
        

3、IO设置(阻塞与非阻塞)

头文件

        <fcntl.h>

        <unistd.h>

1、设置函数
int fcntl(int fd, int cmd, ... /* arg */ );
返回值:
    失败:-1或者错误号
    新的描述符    cmd=F_DUPFD
    描述符标志    cmd=F_GETFD
    文件状态      cmd=F_GETFL
    文件描述符保存的类型    cmd=F_GETLEASE
    描述符的所有者    cmd=F_GETOWN
    管道的容量
        cmd=F_GETPIPE_SZ
        cmd=F_SETPIPE_SZ

参数:
    fd:文件描述符
    cmd:
        复制一个描述符
            F_DUPFD
            F_DUPFD_CLOEXEC
        描述符状态
            F_GETFD    获取
            F_SETFD    设置
        文件状态
            F_GETFL    获取
            F_SETFL    设置


设置为非阻塞步骤:
int old_flag = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, old_flag | O_NONBLOCK);

三、示例

epoll Demo:https://download.csdn.net/download/liutit/85077598

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值