🎈 作者:Linux猿
🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊!
🎈 关注专栏: 数据结构和算法成神路【精讲】优质好文持续更新中……🚀🚀🚀
🎈 欢迎小伙伴们点赞👍、收藏⭐、留言💬
本文主要对 Linux 命令 poll 和 ppoll 命令进行详细讲解,最后会以实例的方式进行说明,下面一起来看下吧!
一、基本概念
poll 和 ppoll 可以同时监听多个文件描述符上的事件,poll 函数和 ppoll 函数之间的关系类似于 select 和 pselect。
二、poll 和 ppoll 函数
2.1 poll 函数
头文件:
#include <poll.h>
声明:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
其中,各参数为:
(1)struct pollfd *fds
该参数是待监控事件的集合,struct pollfd 结构如下所示:
struct pollfd {
int fd; //文件描述符
short events; //需求的事件类型
short revents;//返回的事件类型
};
字段 fd 包含打开文件的文件描述符。如果为负数,则忽略相应的时间字段,并返回 0,。如果此字段指定为零,则 fd 的所有事件都将被忽略,并且 revents 返回 0。
其中,events 和 revents 事件类型有如下种类:
#define POLLIN 0x0001 //有数据需要读取
#define POLLPRI 0x0002 //
#define POLLOUT 0x0004 //可以写入数据
#define POLLERR 0x0008 //调用出错,仅在revents中出现
#define POLLHUP 0x0010 //调用中断,仅在revents中出现
#define POLLNVAL 0x0020 //无效的请求,仅在revents中出现
(2)nfds_t nfds
监听事件的个数,表示 fds 数组的长度。
(3)int timeout
阻塞时间,单位是毫秒,函数调用一直等待,直到发生下列三种情况之一:
- 有事件发生;
- 等待超时;
- 调用被中断;
2.2 ppoll 函数
poll 函数和 ppoll 函数之间的关系类似于 select 和 pselect。
头文件:
#define _GNU_SOURCE
#include <signal.h>
#include <poll.h>
函数声明:
int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask);
函数执行成功返回正数,表示发生事件的描述符的数量;如果返回值为 0,表示调用超时,且没有文件描述符就绪;如果返回 -1,表示出错。
三、实例
下面来看下实例,如下所示:
#include <poll.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
int nfds, num_open_fds;
struct pollfd *pfds;
if (argc < 2)
{
fprintf(stderr, "Usage: %s file...\n", argv[0]);
exit(EXIT_FAILURE);
}
num_open_fds = nfds = argc - 1;
pfds = calloc(nfds, sizeof(struct pollfd));
if (pfds == NULL)
errExit("malloc");
/* Open each file on command line, and add it 'pfds' array. */
for (int j = 0; j < nfds; j++)
{
pfds[j].fd = open(argv[j + 1], O_RDONLY);
if (pfds[j].fd == -1)
errExit("open");
printf("Opened \"%s\" on fd %d\n", argv[j + 1], pfds[j].fd);
pfds[j].events = POLLIN;
}
/* Keep calling poll() as long as at least one file descriptor is
open. */
while (num_open_fds > 0)
{
int ready;
printf("About to poll()\n");
ready = poll(pfds, nfds, -1);
if (ready == -1)
errExit("poll");
printf("Ready: %d\n", ready);
/* Deal with array returned by poll(). */
for (int j = 0; j < nfds; j++)
{
char buf[10];
if (pfds[j].revents != 0)
{
printf(" fd=%d; events: %s%s%s\n", pfds[j].fd,
(pfds[j].revents & POLLIN) ? "POLLIN " : "",
(pfds[j].revents & POLLHUP) ? "POLLHUP " : "",
(pfds[j].revents & POLLERR) ? "POLLERR " : "");
if (pfds[j].revents & POLLIN)
{
ssize_t s = read(pfds[j].fd, buf, sizeof(buf));
if (s == -1)
errExit("read");
printf(" read %zd bytes: %.*s\n",
s, (int)s, buf);
}
else
{ /* POLLERR | POLLHUP */
printf(" closing fd %d\n", pfds[j].fd);
if (close(pfds[j].fd) == -1)
errExit("close");
num_open_fds--;
}
}
}
}
printf("All file descriptors closed; bye\n");
exit(EXIT_SUCCESS);
}
编译程序:
gcc -o main main.c
🎈CSDN博客专家🏆,华为云享专家🏆,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊!
🎈 感觉有帮助记得「一键三连」支持下哦!有问题可在评论区留言💬,感谢大家的一路支持!🤞猿哥将持续输出「优质文章」回馈大家!🤞🌹🌹🌹🌹🌹🌹🤞