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

被折叠的 条评论
为什么被折叠?



