YaoCheng8667 的个人博客

记录精彩的程序人生

Open Source, Open Mind,
Open Sight, Open Future!
  menu
8 文章
0 浏览
1 当前访客
ღゝ◡╹)ノ❤️

select , poll ,epoll的基本用法

1. select

select 系统调用的定义如下:

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

select 系统调用时,向操作系统内核空间会拷贝 3 个 fd_set,分别表示要监控读事件,写事件以及异常事件的 fd 集合,之后内核会对这些 fd 进行轮询,并将相应事件就绪的 fd 拷贝至对应的 fd_set 并在调用结束后将写好的 fd_set 返回至用户空间。

fd_set 内部采用 bitmask 方式进行实现,因此打开的最大 fd 的数目受到一定的限制,由 FD_SETSIZE 常量表示,可以采用如下的 API 进行设置。

#include <sys/select.h>
 
void FD_ZERO(fdset* fds);         /* 将fdset置空 */
void FD_SET(int fd, fdset* fds);  /* fdset添加fd */
void FD_CLR(int fd, fdset* fds);  /* fdset删除fd */
int FD_ISSET(int fd, fdset* fds); /* 当前fd是否设置,若设置返回1,否则返回0*/

2. poll

poll 系统调用的定义如下:

poll(struct pollfd fds[] , int nfds, int timeval);

poll 系统调用的基本流程与 select 类似,区别是传入的是 pollfd 的数组而非 fd_set(bitmask)。因此其数量不会受到限制,在每个 pollfd 结构体中,会标明当前监视的 fd 事件的 bitmask 也就是 events,每次 poll 调用结束,内核会修改 revents 并将其返回。

由于 poll 传入的是一个数组而并非二进制掩码,所以其大小没有限制,使用时只需设置 struct pollfd 相应字段即可。

struct pollfd 的结构如下所示:

struct pollfd{
     int fd;          /*  监听的文件描述符。 */
    short events;    /* 监听事件的bitmask,POLLIN,POLLOUT等  */
    short revents;   /* 返回事件的bitmask  */
}

3.epoll
epoll 系统调用主要提供了 3 个 API:

int epoll_create(int size);
int epoll_ctl(int epfd, int op , int fd , struct epoll_event *ev);
int epoll_wait(int epfd, strct epoll_event* ev,int maxevents ,int timeout);

3.1. epoll_create

epoll_create 创建了一个 epoll 的实例,该实例的 interest_list 为空,调用返回一个代表该 epoll 实例的文件描述符,这个文件描述符不是用于 IO,它代表了一个内核数据结构的句柄。
size 参数指定了一个想要通过 epoll 实例来检查文件描述符的个数,这个参数并不代表着一个上限,而是告诉内核如何为内部结构划分初始大小。

3.2. epoll_ctl

epoll_ctl 能够修改 epoll 实例对应的 interest_list,包括向兴趣列表中添加,修改和删除 fd 的数据等。
op 操作包括:EPOLL_CTL_ADD,EPOLL_CTL_MOD 和 EPOLL_CTL_DEL。
epoll_event 的结构如下所示:

struct epoll_event {
     uint32_t events;       /* events is the bitmask of the epoll_event*/
     epoll_data_t data;     /* data is a union struct of the user_data */
}
typedef union epoll_data{
     void *ptr;
     int fd;
     uint32_t u32;
     uint64_t u64;
}

3.3. epoll_wait

epoll_wait 返回 epoll 实例中就绪的文件描述符信息,返回值为当前就绪的 fd 数量,返回的 event 信息存储在 evlist 数组中,evlist 的空间由用户自行申请,并指定最大返回的事件数量 maxevents 。

timeout 字段用来确定 epoll_wait 的阻塞行为。

  • timeout = 0 : 非阻塞。
  • timeout = -1 : 一直阻塞直到有 event 发生。
  • timeout > 0 : 函数将至多阻塞 timeout 毫秒,直到有 event 发生。

返回事件的种类存储在 evlist 的各个 events 中,使用 bitmask 表示。

常见 events 字段的 bitmask 值有以下几种:

  • EPOLLIN: 可读取非高优先级数据。
  • EPOLLPRI: 可读取高优先级数据。
  • EPOLLOUT: 普通数据可写。
  • EPOLLET: 采用边缘触发方式通知,只可作为 epoll_ctl 输入。
  • EPOLLERR: 表示 event 有错误发生,只可发生在 epoll_wait 返回。

标题:select , poll ,epoll的基本用法
作者:YaoCheng8667
地址:https://ycisme.xyz/articles/2020/04/01/1585707860765.html