博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
总结一下三个io复用函数
阅读量:6007 次
发布时间:2019-06-20

本文共 5935 字,大约阅读时间需要 19 分钟。

1.select  

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

1)nfds为被监听文件描述符的总数,通常为个数+1

2)struct fd_set由定义来看__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];包含一个整形数组,其中每个位代表着一个文件描述符,这代表了读文件描述符的集合。需要注意的是,监听文件描述符的最大数由fd_setsize决定,其最大值是1024。

3)代表写文件描述符的集合。

4)异常文件描述符的集合。

5)struct timeout结构

struct timeval  {    __time_t tv_sec;        /* Seconds.  */    __suseconds_t tv_usec;    /* Microseconds.  */  };

第一个成员为秒,第二个成员为微妙,可见提供到微妙的支持。如果该结构指定为null,则一直阻塞此函数直到有事件发生。

6)return:成功返回0,失败返回-1并置errno。

7)提供以下宏函数代替位的繁琐操作

#define    FD_SET(fd, fdsetp)    __FD_SET (fd, fdsetp)  //将文件描述符置位,相当于加入到该集合当中。#define    FD_CLR(fd, fdsetp)    __FD_CLR (fd, fdsetp)  //清除该文件描述符上的位,相当于从集合中取出。#define    FD_ISSET(fd, fdsetp)    __FD_ISSET (fd, fdsetp)  //判断文件描述符是否在其中#define    FD_ZERO(fdsetp)        __FD_ZERO (fdsetp)  //将该文件描述符清零。

8)更要注意的是,在向内核注册事件,通知完该事件之后,一定要重新注册一遍,即fd_set需要重新FD_SET进文件描述符。因为只能监听3个事件,读写异常,所以限制较多。

2.poll

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

1)struct pollfd结构

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

  1.1)events是需要在该文件描述符上监听的事件,通常是下列宏的位掩码:

POLLIN               //该文件描述符有数据可读              There is data to read.                    POLLPRI        //紧急数据(oob)                     There is urgent data to read (e.g., out-of-band  data  on                     TCP socket; pseudoterminal master in packet mode has seen                     state change in slave).              POLLOUT        //写的缓冲区现在不阻塞了,可以该描述符写东西                     Writing now will not block.              POLLRDHUP (since Linux 2.6.17)    //仅linux支持,文件描述符对方关闭了写,或者关闭了连接,这个很有必要知道                     Stream socket peer closed connection, or shut down  writ‐                     ing  half  of  connection.   The _GNU_SOURCE feature test                     macro must be defined (before including any header files)                     in order to obtain this definition.              POLLERR        //错误事件                     Error condition (output only).                  POLLHUP        //挂起                     Hang up (output only).              POLLNVAL      //文件描述符不有效                     Invalid request: fd not open (output only).   如果定义了_XOPEN_SOURCE,那么还有如下的宏:

          POLLRDNORM       //normal,正常的可读数据,相当与pollin

              Equivalent to POLLIN.

          POLLRDBAND    //linux中不可用

                       Priority band data can be read (generally unused onLinux).

          POLLWRNORM    //相当于pollout

                       Equivalent to POLLOUT.

          POLLWRBAND    //更高优先级的数据可写

              Priority data may be written.

  1.2)内核返回的事件。

2)文件描述符的总数,typeof unsigned long int nfds_t

3)监听时间,指定为0立即返回,指定为-1则一直阻塞直到所监听描述符上有事件发生。

4)return:正常返回0,异常返回-1并置errno

3.epoll

//需要如下的一组函数来完成         *  epoll_create(2)  creates  an  epoll  instance  and  returns  a  file                 descriptor  referring to that instance.  (The more recent epoll_cre‐          ate1(2) extends the functionality of epoll_create(2).)                      *  Interest in particular  file  descriptors  is  then  registered  via              epoll_ctl(2).   The  set of file descriptors currently registered on          an epoll instance is sometimes called an epoll set.       *  epoll_wait(2) waits for I/O events, blocking the calling  thread  if          no events are currently available.

1)向内核注册事件表,参数为需要监听的文件描述符的个数。

2)extern int epoll_ctl (int __epfd, int __op, int __fd,struct epoll_event *__event) __THROW;  //类似于fcntl函数

  2.1)指定的epollfd事件表的描述符

  2.2)op操作的类型,有如下的宏可选

#define EPOLL_CTL_ADD 1    /* Add a file descriptor to the interface.  */       //添加#define EPOLL_CTL_DEL 2    /* Remove a file descriptor from the interface.  */   //删除#define EPOLL_CTL_MOD 3    /* Change file descriptor epoll_event structure.  */  //修改

  2.3)需要监听的文件描述符

  2.4)struct epoll_event结构

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

    2.4.1)events为需要监听事件的位掩码,如下所示

enum EPOLL_EVENTS  {    EPOLLIN = 0x001,          //有数据可读#define EPOLLIN EPOLLIN    EPOLLPRI = 0x002,    //有紧急数据(oob)可读#define EPOLLPRI EPOLLPRI    EPOLLOUT = 0x004,    //该描述符有缓冲区可供写#define EPOLLOUT EPOLLOUT    EPOLLRDNORM = 0x040,      //normal#define EPOLLRDNORM EPOLLRDNORM    EPOLLRDBAND = 0x080,        //优先级数据可读#define EPOLLRDBAND EPOLLRDBAND    EPOLLWRNORM = 0x100,      //normal write#define EPOLLWRNORM EPOLLWRNORM    EPOLLWRBAND = 0x200,      //优先级数据可写#define EPOLLWRBAND EPOLLWRBAND    EPOLLMSG = 0x400,        //没了解过#define EPOLLMSG EPOLLMSG    EPOLLERR = 0x008,#define EPOLLERR EPOLLERR       //错误消息    EPOLLHUP = 0x010,#define EPOLLHUP EPOLLHUP    //挂起    EPOLLRDHUP = 0x2000,#define EPOLLRDHUP EPOLLRDHUP    //描述符的对方关闭了写操作,或者关闭了连接    EPOLLWAKEUP = 1u << 29,#define EPOLLWAKEUP EPOLLWAKEUP    //没了解    EPOLLONESHOT = 1u << 30,#define EPOLLONESHOT EPOLLONESHOT  //在任意时刻仅可以触发一个可读可写异常事件,常用与多线程    EPOLLET = 1u << 31#define EPOLLET EPOLLET   //使用et方式工作,默认lt  };

    2.4.2)

typedef union epoll_data{  void *ptr;  int fd;  uint32_t u32;  uint64_t u64;} epoll_data_t;

  可以看出是一个union,ptr指的是数据地址,fd指的是文件描述符,通常我们使用文件描述符。

    2.4.3)关于et(边缘敏感)与lt(水平敏感):lt模式:通知之后可不处理。et:通知之后必须处理,且对该事件仅通知一次

  2.5)成功返回0,失败返回-1

3)

extern int epoll_wait (int __epfd, struct epoll_event *__events,               int __maxevents, int __timeout);

  3.1)指定的epollfd

  3.2)触发事件的数组集合

  3.3)需要监听的最大描述符数量

  3.4)timeout,-1则一直阻塞直到有事件发生。

  3.5)返回有发生事件的文件描述符个数。

4)通常我们要往一个epollfd添加文件描述符的函数接口可以这么写:

void addfd(int epollfd,int fd){    struct epoll_event event;    event.data.fd=fd;    event.events=EPOLLIN|EPOLLET;    epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);    setnonblocking(fd);}

5)通常设置一个文件描述符为非阻塞可以这么写:

int setnonblocking(int fd){    int old_option=fcntl(fd,F_GETFL);    int new_option=old_option|O_NONBLOCK;    fcntl(fd,F_SETFL,new_option);    return old_option;}

4.详情请看man或者源码

转载于:https://www.cnblogs.com/manch1n/p/10555815.html

你可能感兴趣的文章
JavaScript 设计模式
查看>>
Java EE供应商和伦敦Java用户组宣布新的MicroProfile
查看>>
PostgreSQL中的大容量空间探索时间序列数据存储
查看>>
敏捷制造:并不是你想像的矛盾体
查看>>
jQuery选择器和事件
查看>>
十、syslog日志与loganalyzer日志管理
查看>>
Python多进程并发写入PostgreSQL数据表
查看>>
mysql 优化
查看>>
2.4 salt grains与pillar jinja的模板
查看>>
简单的验证码程序
查看>>
MySQL主从(介绍,配置主机,配置从机,测试主从同步)
查看>>
不同版本的outlook客户端配置Office 365 exchange online帐户需要安装的补丁
查看>>
Java服务器-resin
查看>>
Linux下搭建JDK和TOMCAT环境
查看>>
关闭windows休眠
查看>>
Ansible之十一:变量详解
查看>>
那些SCOM 管理包开发中遇到的坑1–Powershell scriptBlock Invoke执行结果的类型
查看>>
关于Server Sql 2008触发器的使用
查看>>
mac常见命令
查看>>
Redhat 系统相关调优参数注解
查看>>