11月17日笔记网络编程5_多路复用(select,poll,epoll)

1.多路复用:监听多个文件描述符是否就绪(read/write/error)
    阻塞IO
        (1)读
            没有数据可读 read(类似的)函数就会阻塞(wait)
            直到有数据或出错为止
        (2)写
            没有空间去写 write(类似的)函数就会阻塞(wait)
            直到出现错误或者有空间可以写
        内核默认的一种IO方式 也是最简单的方式
    多路复用 (种类)
    (1)select

    (2)poll 
        -->epoll


2.select

    NAME
        select,  pselect,  FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multi‐
        plexing

    SYNOPSIS
        /* According to POSIX.1-2001, POSIX.1-2008 */
        #include <sys/select.h>

        /* According to earlier standards */
        #include <sys/time.h>
        #include <sys/types.h>
        #include <unistd.h>

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

                nfds          :感兴趣的最大文件描述符+1
                readfds     :需要监听读的文件描述符集合
                writefds    :需要监听写的文件描述符集合
                exceptfds :需要监听出错的文件描述符集合
                    三个参数都可以为NULL 等效于一个延时函数
                    调用前,调用者填入的是 感兴趣的文件的文件描述符
                    调用后  保存的是已经就绪的文件描述符
                timeout:超时设置

                struct timeval {
                        long    tv_sec;   秒
                        long    tv_usec;  微秒
                    };

                    在调用前填的    超时时间
                    调用后保存的是  剩余时间
            返回值
                >0 表示就绪的文件描述符的个数
                =0 表示超时了
                <0 出错了

        void FD_CLR(int fd, fd_set *set);

            将文件描述符fd从fd_set这个集合移除

        int  FD_ISSET(int fd, fd_set *set);

            判断这个文件描述符fd是否在集合fd_set中

        void FD_SET(int fd, fd_set *fd_set);

            将文件描述符fd加入到set这个集合中去

        void FD_ZERO(fd_set *fd_set);

            将一个集合set全部清除

        select的实现 是在内核中开辟一个 内核线程 去实现的
            同时监听。轮询

            while(没有超时)
            {
                先问第一个文件描述符是否准备就绪 [0,nfds)
                ..... 根据循环一致往后问
                if(有文件就绪了)
                {
                    记录那个文件就绪了
                    break;
                }
                sleep(1);
            }
    


3.poll

    NAME
        poll, ppoll - wait for some event on a file descriptor

    SYNOPSIS
        #include <poll.h>
            poll功能和select是类似的 "监听"多个文件描述符 是否就绪
            只不过 poll用一个结构体struct pollfd来描述 “监听请求”
            struct pollfd {
               int       fd;         /* file descriptor */
               short   events;     /* 监听的事件 */ 位域
                                    POLLIN        :可读的事件
                                    POLLOUT    :可写的事件
                                    POLLERR    :出错的事件
                                如果你要监听 可读可写怎么办?
                                    POLLIN | POLLOUT
               short  revents;    /* returned events */ 位域
                                保存的是已经就绪的事件
                                怎么判断是否可读
                                if(revents & POLLIN)
                                {
                                    可读了
                                }
           };

        一个结构体只能表示一个文件 多个文件怎么办?
        结构体数组

        int poll(struct pollfd *fds, nfds_t nfds, int timeout);

            fds        :需要监听的struct pollfd 结构体数组
            nfds      :数组中有几个元素 要监听几个文件描述符
            timeout :超时时间 单位毫秒
        返回值
            >0 表示就绪的文件描述符的个数
            =0 表示超时了
            <0 出错了


4.epoll
    (1)epoll_create:创建一个监听文件的集合,这个函数的返回值也是一个文件描述符

    NAME
        epoll_create, epoll_create1 - open an epoll file descriptor

    SYNOPSIS
        #include <sys/epoll.h>

        int epoll_create(int size);

                size :已经被忽略了 但是size还是要大于0
        
            返回值
                成功 返回一个epoll对象(实例),就是一个文件描述符
                失败 返回-1 同时errno被设置
            
            对象有了,但是怎么把需要监听的文件加入到这个对象中去呢?
    (2)epoll_ctl

    NAME
        epoll_ctl - control interface for an epoll file descriptor

    SYNOPSIS
        #include <sys/epoll.h>

        int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

                epfd     :epoll的对象 也就是 epoll_create的返回值
                op        :具体的操作
                    EPOLL_CTL_ADD
                        把一个需要监听的文件描述符和需要监听的事件添加到epoll对象中去
                    EPOLL_CTL_MOD :
                        修改一个已经在epoll对象中文件描述符的监听事件
                    EPOLL_CTL_DEL :
                        从一个epoll对象中删除一个文件描述符
                fd        :要操作的文件描述符
                event  :要监听事件的结构体指针

                    struct epoll_event 
                    {
                        uint32_t         events;      /* Epoll events */
                        epoll_data_t  data;        /* User data variable */
                    };

                    先看events
                        要监听的事件标志 位域
                            EPOLLIN          :可读的事件
                            EPOLLOUT      :可写事件
                            EPOLLERR      :出错事件
                            EPOLLRDHUP : 监听流式套接字的对方
                                是否已经关闭写或者关闭读写
                            EPOLLET         :边缘触发 Edge-Triggered
                                LT  Level-Triggered 等级触发
                                    只要有数据就会不停的上报可读
                                ET  Edge-Triggered 边缘触发
                                    需要数据量发生变化才会上报可读

                    data        : 用来保存用户的一些数据的

                        typedef union epoll_data 
                        {
                            void        *ptr;//保存用户数据指针
                            int          fd;
                            uint32_t     u32;
                            uint64_t     u64;
                        } epoll_data_t;

                返回值
                    成功返回0  失败返回-1同时errno被设置
    (3)epoll_wait:用来等待监听事件的发生

    NAME
        epoll_wait, epoll_pwait - wait for an I/O event on an epoll file descriptor

    SYNOPSIS
        #include <sys/epoll.h>
            监听epoll对象中的文件描述符的事件
        int epoll_wait(int epfd, struct epoll_event *events,
                        int maxevents, int timeout);

                epfd            :epoll的对象
                events        :结构体数据 用来保存已经就绪的事件信息 这是数组
                maxevents :第二个结构体数组最多可以保存多少个元素
                timeout       :超时时间 单位ms
            返回值
                >0 表示就绪的文件描述符的个数
                =0 表示超时了
                <0 出错了
        优点
            1.效率比poll要高
                在文件描述符比较多的时间 poll需要去看每一个文件描述对应的事件是否就绪
                epoll直接只返回那些文件描述符需要监听的事件就绪
            2.边缘触发的功能



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值