简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:理解poll和epoll用法区别与总结。
2.代码示例
<1>.poll用法讲解
poll
函数用于实现多路复用(multiplexing),即通过等待多个文件描述符上的事件发生来进行 I/O 操作,而不阻塞整个程序。它是一种用于实现非阻塞 I/O 的方法,可以提高程序的性能和响应能力。
poll
函数的主要作用是监视一组文件描述符(通常是套接字)的状态,并在其中任何一个文件描述符上发生事件时进行相应处理。它可以同时监视多个文件描述符的可读、可写和异常事件。
以下是 poll
函数的一般用法:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds
是一个指向pollfd
结构体数组的指针,每个结构体表示一个被监视的文件描述符及其关注的事件。nfds
是fds
数组中结构体的数量。timeout
是指定的等待时间,单位是毫秒
<2>.poll代码实例
#include <iostream>
#include <poll.h>
#include <unistd.h>
int main() {
// 创建 pollfd 数组
struct pollfd fds[1];
// 添加需要监听的套接字到 pollfd 数组中
fds[0].fd = STDIN_FILENO;/* 套接字文件描述符 */;
fds[0].events = POLLIN; // 监听可读事件
// 开始监听事件
while (true) {
int ret = poll(fds, 1, -1);
if (ret > 0) {
if (fds[0].revents & POLLIN) {
// 可读事件发生在套接字上
char buffer[256];
ssize_t bytesRead = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
if (bytesRead > 0) {
buffer[bytesRead] = '\0';
std::cout << "Received input: " << buffer << std::endl;
}
}
} else if (ret == -1) {
std::cerr << "Error while polling" << std::endl;
break;
}
}
return 0;
}
<3>.epoll用法讲解
epoll是一个高效的事件通知机制,用于处理I/O事件。它是Linux操作系统提供的一种异步I/O模型,常用于服务器编程中。其主要作用是监听多个I/O事件,并在发生事件时进行相应的处理。
使用epoll机制可以避免传统的阻塞I/O模型中频繁的轮询操作,提高系统的性能和并发处理能力。它可以管理大量的文件描述符(sockets),并通过回调函数或其他方式提供有效的事件通知机制。当有I/O事件发生时,操作系统会通知应用程序,使得应用程序可以及时处理相关的I/O操作。
epoll通过三个函数epoll_create、epoll_ctl和epoll_wait来完成相关的操作。epoll_create用于创建一个epoll句柄(文件描述符),epoll_ctl用于添加、修改或删除监听的文件描述符,而epoll_wait则是等待事件的发生并进行处理。
总的来说,epoll在C++中的作用是提供高效的异步I/O事件通知机制,使得服务器程序可以高效地处理大量的并发连接和I/O操作。
<4>.epoll实例
#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>
#define MAX_EVENTS 10
#define MAX_BUF_SIZE 1024
int main() {
int epoll_fd, event_count;
struct epoll_event event, events[MAX_EVENTS];
char buffer[MAX_BUF_SIZE];
// 创建epoll句柄
epoll_fd = epoll_create1(0);
if (epoll_fd == -1) {
std::cerr << "Failed to create epoll file descriptor." << std::endl;
return 1;
}
// 设置监听的文件描述符
event.data.fd = STDIN_FILENO; // 监听标准输入
event.events = EPOLLIN; // 监听可读事件
// 将监听事件添加到epoll句柄中
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) {
std::cerr << "Failed to add file descriptor to epoll." << std::endl;
close(epoll_fd);
return 1;
}
while (true) {
// 等待事件发生
event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
if (event_count == -1) {
std::cerr << "Failed to wait for events." << std::endl;
close(epoll_fd);
return 1;
}
// 处理所有发生的事件
for (int i = 0; i < event_count; ++i) {
// 如果是标准输入可读事件
if (events[i].data.fd == STDIN_FILENO) {
// 读取用户输入
int read_count = read(STDIN_FILENO, buffer, MAX_BUF_SIZE);
if (read_count == -1) {
std::cerr << "Failed to read from standard input." << std::endl;
close(epoll_fd);
return 1;
}
// 将读取到的内容打印出来
std::cout << "Read from standard input: " << buffer << std::endl;
}
}
}
// 关闭epoll句柄
close(epoll_fd);
return 0;
}