【Linux】IO复用之poll系统调用
2021/8/8 7:08:34
本文主要是介绍【Linux】IO复用之poll系统调用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 一、poll 系统调用解释
- 1. poll 函数原型解释
- 2. struct pollfd 结构体
- 3. events/revents 含义
- 4. 图解 事件结构数组
- 二、poll 系统调用代码演示 之 监控标准输入
一、poll 系统调用解释
poll 没有 select 跨平台性能优越
poll 没有 epoll 性能高
故 poll 我们只做简单了解
1. poll 函数原型解释
poll系统调用功能:poll() 执行与 select 类似的任务,它等待一组文件描述符中的一个就绪的 I/O。
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds
:需要监控的事件结构数组
,即struct pollfd arr[N]
nfds
:事件结构数组中有效元素的个数timeout
:阻塞等待时间长度,0 表示立即返回,小于 0 表示无限制阻塞,大于 0 表示阻塞 timeout 毫秒- 返回值:大于 0 表示就绪的文件描述符的个数;等于 0 表示超时;小于 0 表示监控出错
如果任何文件描述符都没有发生请求的事件(并且没有错误),则 poll() 将阻塞,直到其中一个事件发生。
2. struct pollfd 结构体
内核中源码定义:
struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ };
其中events
是入参
需要设置的,而revents
是出参
,是由poll
函数内部设置好返回出来的
fd
:需要监控的文件描述符,字段 fd 包含打开文件的文件描述符。 如果此字段为负,则忽略相应的 events 字段并且 revents 字段返回零。 (这提供了一种忽略单个 poll 调用的文件描述符的简单方法:简单地否定 fd 字段。)events
:字段 events 是一个输入参数
,一个掩码位指定应用程序对文件描述符 fd 感兴趣的事件。 如果此字段指定为零,则 fd 的所有事件都将被忽略,并且 revents 返回零。revents
:字段 revents 是一个输出参数
,由内核填充实际发生的事件。 revents 中返回的位可以包括事件中指定的任何位,或者值 POLLERR、POLLHUP 或 POLLNVAL 之一。 (这三个位在 events 字段中没有意义,只要相应的条件为真,就会在 revents 字段中设置。)
3. events/revents 含义
可以在 events/revents 中 设置/返回 的位在 <poll.h> 中定义如下:
/* These are specified by iBCS2 */ #define POLLIN 0x0001 // 0000 0001 #define POLLPRI 0x0002 // 0000 0010 #define POLLOUT 0x0004 // 0000 0100 #define POLLERR 0x0008 // 0000 1000 #define POLLHUP 0x0010 // 0001 0000 #define POLLNVAL 0x0020 // 0010 0000
POLLIN
:表示有数据要读取POLLPRI
:表示有紧急数据要读取(例如:TCP 套接字上的带外数据)POLLOUT
:表示现在写不会阻塞POLLERR
:错误条件(仅输出)POLLHUP
:流套接字对等关闭连接或关闭写入一半的连接, 必须定义 _GNU_SOURCE 功能测试宏(在包含任何头文件之前)才能获得此定义。POLLNVAL
:无效请求:fd 未打开(仅输出)。
若想同时设置多个属性,只需将宏按位或运算
即可,例如:POLLIN | POLLOUT
4. 图解 事件结构数组
表示事件结构数组中有2个有效元素,poll 只需要监控前两个即可
二、poll 系统调用代码演示 之 监控标准输入
poll.cpp
#include <iostream> #include <poll.h> #include <string> #include <unistd.h> #define FDNUMS 10 #define POLLERROR (-1) using namespace std; int main() { // 构造poll入参 struct pollfd arrFD[FDNUMS]; arrFD[0].fd = 0; arrFD[0].events = POLLIN; int nfds = 1; int timeout = 10; loop: int ret = poll(arrFD, nfds, timeout); if(ret == 0) // 超时重新监控 goto loop; else if(ret < 0) // 监控出错 { perror("poll"); return POLLERROR; } // stdin文件描述符已就绪 for(int i = 0; i < FDNUMS; i++) { // 从标准输入中读取用户输入的数据,再输出 if(arrFD[i].revents == POLLIN) { char str[1024] = { 0 }; read(arrFD[i].fd, str, sizeof(str) - 1); cout << "stdin : " << str; } } return 0; }
[gongruiyang@localhost poll]$ g++ poll.cpp -o poll [gongruiyang@localhost poll]$ ./poll hello world! stdin : hello world!
这篇关于【Linux】IO复用之poll系统调用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法