fcntl、select、poll、epoll使用

本文介绍了Linux系统中的四个I/O多路复用函数:fcntl用于文件描述符操作,select用于事件检测,poll提供低级事件通知,而epoll则提供了更高效、面向事件驱动的机制。它们在处理大量并发连接时提高效率,支持非阻塞和阻塞模式以及自定义事件处理。

1. fcntl

#include <unistd.h>

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

cmd:

复制一个现有的描述符(cmd=F_DUPFD).

获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).

获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).

获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).

获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).

arg:

O_NONBLOCK,非阻塞,配合F_SETFL使用。

返回值:成功返回文件描述符fd的属性位图,失败返回-1。

2. select

#include <sys/select.h>

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

nfds:最大的文件描述符+1;

readfds:输入输出型参数,设置读事件的fd位图;

writefds:输入输出型参数,设置写事件的fd位图;

exceptfds:输入输出型参数,设置异常事件的fd位图;

timeout:输入输出型参数,未超时返回会设置剩余时间。

struct timeval

  {

    __time_t tv_sec;    /* Seconds.  */

    __suseconds_t tv_usec; /* Microseconds.  */

  };

nullptr,阻塞;{0,0},非阻塞;{5,0},设置超时时间,每阻塞5秒返回一次。

返回值:成功返回就绪的文件描述符数量,失败返回-1。

fd_set:

void FD_CLR(int fd, fd_set *set); // 用来清除描述词组set中相关fd的位

int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组set中相关fd的位是否为真

void FD_SET(int fd, fd_set *set); // 用来设置描述词组set中相关fd的位

void FD_ZERO(fd_set *set); // 用来清除描述词组set的全部

3. poll

#include <poll.h>

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

fds:是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返回的事件集合.

struct pollfd

  {

    int fd;       /* File descriptor to poll.  */

    short int events;      /* Types of events poller cares about.  */

    short int revents;     /* Types of events that actually occurred.  */

  };

如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1,poll不再监控此pollfd。

nfds:表示fds数组的长度;

timeout:表示poll函数的超时时间, 单位是毫秒(ms),-1阻塞,0非阻塞,大于0超时时间。

返回值:成功返回就绪的文件描述符数量,失败返回-1。

3.1 poll函数事件标志宏

4. epoll

#include <sys/epoll.h>

int epoll_create(int size);

size:节点大小,已被忽略。

返回值:成功返回epoll句柄(文件描述符),失败返回-1.

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

epfd:epoll句柄;

op:执行动作

EPOLL_CTL_ADD :注册新的fd到epfd中;

EPOLL_CTL_MOD :修改已经注册的fd的监听事件;

EPOLL_CTL_DEL :从epfd中删除一个fd.

fd:要监听的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 */

}

EPOLLIN : 表示对应的文件描述符可以读 (包括对端SOCKET正常关闭);

EPOLLOUT : 表示对应的文件描述符可以写;

EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 (这里应该表示有带外数据到来);

EPOLLERR : 表示对应的文件描述符发生错误;

EPOLLHUP : 表示对应的文件描述符被挂断;

EPOLLET : 将EPOLL设为边缘触发(Edge Triggered)模式, 这是相对于水平触发(Level Triggered)来说的.

EPOLLONESHOT:只监听一次事件, 当监听完这次事件之后, 如果还需要继续监听这个socket的话, 需要再次把这个socket加入到EPOLL队列里.

返回值:成功返回0,失败返回-1.

int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);

epfd:epoll句柄;

events:输出型参数,已就绪fd;

maxevents:要获取得最大已就绪fd数量;

timeout:表示epoll函数的超时时间, 单位是毫秒(ms),-1阻塞,0非阻塞,大于0超时时间。

返回值:成功返回就绪的文件描述符数量,失败返回-1。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值