poll的介绍

poll 系统调用详解
poll 是 Linux/Unix 系统中用于 多路复用 I/O 操作 的系统调用,允许程序同时监听多个文件描述符(File Descriptor, FD)的状态变化(如可读、可写、错误等)。它是 select 的改进版,解决了 select 的某些局限性。

  1. 核心功能
    监听多个文件描述符:同时监控多个 FD 的状态(如套接字、管道、设备文件等)。

阻塞与非阻塞:可设置超时时间,实现阻塞或非阻塞等待。

事件驱动:当任一被监听的 FD 就绪(如数据可读、可写)时,立即返回。

  1. 函数原型
    c
    #include <poll.h>

int poll(struct pollfd fds, nfds_t nfds, int timeout);
参数说明
参数 类型 说明
fds struct pollfd
指向 pollfd 结构体数组,每个元素描述一个待监听的 FD 和事件。
nfds nfds_t 数组 fds 的长度(即监听的 FD 数量)。
timeout int 超时时间(毫秒):

  • 0:等待指定毫秒后返回。

  • 0:非阻塞,立即返回。
  • -1:阻塞,直到有事件发生。
    返回值
    返回值 说明

0 返回就绪的 FD 数量(可处理的事件数)。
0 超时且无 FD 就绪。
-1 出错(如被信号中断),可通过 errno 获取错误码(如 EINTR)。

  1. struct pollfd 结构体
    c
    struct pollfd {
    int fd; // 监听的文件描述符
    short events; // 监听的事件(按位掩码)
    short revents; // 实际发生的事件(由内核填充)
    };
    常用事件标志
    事件 说明
    POLLIN FD 有数据可读(如 Socket 收到数据)。
    POLLOUT FD 可写(如 Socket 发送缓冲区未满)。
    POLLERR FD 发生错误(仅用于 revents,不可设置在 events 中)。
    POLLHUP FD 挂起(如对端关闭连接)。
    POLLNVAL FD 未打开(无效描述符)。
  2. 工作流程
    初始化 pollfd 数组:
    指定需要监听的 FD 和事件(如 POLLIN)。

调用 poll:
阻塞等待,直到 FD 就绪或超时。

检查返回值:

若 >0,遍历 pollfd 数组,通过 revents 判断哪些 FD 就绪。

若 0,处理超时逻辑。

若 -1,处理错误。

  1. 代码示例
    监听标准输入和Socket
    c
    #include <poll.h>
    #include <stdio.h>
    #include <unistd.h>

int main() {
struct pollfd fds[2];

// 监听标准输入(fd=0)
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;

// 监听一个假设的Socket(fd=4)
fds[1].fd = 4;
fds[1].events = POLLIN | POLLOUT;

while (1) {
    int ret = poll(fds, 2, 5000); // 阻塞5秒
    if (ret == -1) {
        perror("poll error");
        break;
    } else if (ret == 0) {
        printf("Timeout.\n");
        continue;
    }

    // 检查哪些FD就绪
    if (fds[0].revents & POLLIN) {
        printf("stdin is readable.\n");
    }
    if (fds[1].revents & POLLIN) {
        printf("socket is readable.\n");
    }
    if (fds[1].revents & POLLOUT) {
        printf("socket is writable.\n");
    }
}
return 0;

}
6. poll vs select
特性 poll select
FD 数量限制 无限制(基于数组) 受 FD_SETSIZE 限制(通常1024)
效率 高(无需每次重置 FD 集合) 低(需每次重建 fd_set)
内核实现 更现代 较老旧
可移植性 多数 Unix/Linux 所有平台
7. 常见问题
(1) 为什么用 poll 而不是 select?
poll 支持更多的 FD(select 默认限制为1024)。

poll 不需要每次调用前重新初始化 FD 集合。

(2) poll 的缺点
水平触发(LT):就绪事件需及时处理,否则会重复通知(对比 epoll 的 ET 模式)。

性能问题:当监听大量 FD 时,遍历数组效率较低(此时 epoll 更优)。

(3) 替代方案
epoll(Linux特有):高性能多路复用,适合海量连接。

kqueue(FreeBSD/macOS):类似 epoll。

  1. 总结
    poll 适用场景:
    ✅ 监听少量到中等数量的 FD(如 <1000)。
    ✅ 需要跨平台兼容性(相比 epoll)。

核心步骤:

初始化 pollfd 数组。

调用 poll 阻塞等待。

遍历检查 revents。

扩展学习:

epoll(Linux 高性能网络编程)。

libevent(跨平台事件库,封装 poll/epoll)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值