IO多路复用几种函数

1. select()

函数原型

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

参数说明

  • nfds:指定文件描述符的范围。这个值应设置为所有文件描述符中最大值加一。例如,如果监视的文件描述符是 0 到 5,则 nfds 应设置为 6。
  • readfds:指向一个 fd_set 结构体的指针,该结构体表示要监视的可读文件描述符集合。调用 select() 之前,需要使用 FD_ZERO() 初始化该集合,并用 FD_SET() 添加文件描述符。调用 select() 后,集合中的文件描述符将更新为实际发生可读事件的文件描述符。
  • writefds:指向一个 fd_set 结构体的指针,该结构体表示要监视的可写文件描述符集合。用法与 readfds 类似。
  • exceptfds:指向一个 fd_set 结构体的指针,该结构体表示要监视的异常条件集合。用法与 readfds 类似。
  • timeout:指向一个 struct timeval 结构体的指针,表示 select() 的超时时间。如果超时前没有文件描述符状态变化,select() 将返回。如果设置为 NULL,则表示 select() 将无限期等待直到有事件发生。

返回值

 

优势

 

  • 成功:返回发生事件的文件描述符数量。
  • 失败:返回 -1,并设置 errno
    #include <sys/select.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main() {
        fd_set read_fds;
        struct timeval timeout;
        int max_fd = 0;  // 最大文件描述符编号
    
        // 初始化文件描述符集
        FD_ZERO(&read_fds);
        FD_SET(STDIN_FILENO, &read_fds);  // 监视标准输入
    
        timeout.tv_sec = 5;  // 设置超时时间为5秒
        timeout.tv_usec = 0;
    
        int ret = select(max_fd + 1, &read_fds, NULL, NULL, &timeout);
        if (ret == -1) {
            perror("select");
            return 1;
        } else if (ret == 0) {
            printf("Timeout occurred!\n");
        } else {
            if (FD_ISSET(STDIN_FILENO, &read_fds)) {
                printf("Data is available on stdin\n");
            }
        }
    
        return 0;
    }
    
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

    2. poll()

  • 介绍

    poll() 是另一种 I/O 多路复用机制,允许应用程序监视多个文件描述符,等待它们的状态发生变化。与 select() 不同,poll() 使用一个数组来表示文件描述符。

    工作原理

  • 结构体poll() 使用 pollfd 结构体数组,其中包含要监视的文件描述符及其事件类型。
  • 事件类型pollfd 结构体中的 events 成员表示感兴趣的事件(如 POLLINPOLLOUT)。
  • 返回值:返回值表示活动的文件描述符数量。可以通过检查 revents 成员来判断哪个文件描述符有事件发生。
  • 文件描述符数量限制:没有像 select() 那样的文件描述符数量限制,只受限于系统的内存。
  • 性能改进:对大量文件描述符的处理性能较 select() 更好。
#include <poll.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    struct pollfd fds[1];
    int ret;

    fds[0].fd = STDIN_FILENO;
    fds[0].events = POLLIN;  // 关注可读事件

    ret = poll(fds, 1, 5000);  // 超时时间为5000毫秒
    if
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3. epoll() 

介绍

epoll() 是 Linux 特有的 I/O 多路复用机制,设计用于高效处理大量文件描述符,尤其适合需要高性能的网络服务和其他 I/O 密集型应用。epoll 提供了更好的扩展性和性能,尤其在处理大量文件描述符时优于 select()poll()

epoll_create()

函数原型

int epoll_create(int size);
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  • size:指定 epoll 实例的初始大小,但在现代 Linux 内核中,这个参数已被忽略。你可以传递任意值,但通常设置为 1。

返回值

  • 成功:返回一个新的 epoll 文件描述符。
  • 失败:返回 -1,并设置 errno
  •  

 epoll_ctl()

函数原型

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

参数说明

  • epfd:由 epoll_create() 返回的 epoll 文件描述符。
  • op:操作类型,取值为 EPOLL_CTL_ADD(添加文件描述符)、EPOLL_CTL_MOD(修改文件描述符)或 EPOLL_CTL_DEL(删除文件描述符)。
  • fd:要添加、修改或删除的文件描述符。
  • event:指向 epoll_event 结构体的指针,指定感兴趣的事件及事件处理的用户数据。

返回值

  • 成功:返回 0。
  • 失败:返回 -1,并设置 errno
  •  

epoll_wait()

函数原型

 

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

参数说明

  • epfd:由 epoll_create() 返回的 epoll 文件描述符。
  • events:指向 epoll_event 结构体数组的指针。epoll_wait() 将把发生事件的文件描述符及其事件填充到这个数组中。
  • maxeventsevents 数组的大小,即最大事件数量。
  • timeout:超时时间(以毫秒为单位)。设置为 0 表示非阻塞模式,设置为 -1 表示无限期等待。

返回值

  • 成功:返回发生事件的文件描述符数量。
  • 失败:返回 -1,并设置 errno
struct epoll_event {
    uint32_t events;      // 事件类型,例如 EPOLLIN、EPOLLOUT
    epoll_data_t data;    // 用户数据,通常用于保存文件描述符
};

常用事件标志

  • EPOLLIN:文件描述符可读。
  • EPOLLOUT:文件描述符可写。
  • EPOLLERR:发生错误。
  • EPOLLET:边沿触发模式(ET),文件描述符会在事件到达时通知一次
#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>

#define MAX_EVENTS 10

int main() {
    int epfd = epoll_create(1);
    if (epfd == -1) {
        perror("epoll_create");
        return 1;
    }

    struct epoll_event ev, events[MAX_EVENTS];
    ev.events = EPOLLIN;  // 关注可读事件
    ev.data.fd = STDIN_FILENO;

    if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1) {
        perror("epoll_ctl");
        return 1;
    }

    int nfds = epoll_wait(epfd, events, MAX_EVENTS, 5000);  // 等待最多5000毫秒
    if (nfds == -1) {
        perror("epoll_wait");
        return 1;
    } else if (nfds == 0) {
        printf("Timeout occurred!\n");
    } else {
        for (int i = 0; i < nfds; i++) {
            if (events[i].events & EPOLLIN) {
                printf("Data is available on stdin\n");
            }
        }
    }

    close(epfd);
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值