[英]Why is epoll_wait not responding to terminal input?
The following code, when ran, does not respond to terminal input.以下代码在运行时不响应终端输入。 I have ran this under Debian 10.5.0 and CentOS 7 with the same results.
我在 Debian 10.5.0 和 CentOS 7 下运行它,结果相同。 What am I missing?
我错过了什么?
#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
char buffer[4096];
int fd = epoll_create1(EPOLL_CLOEXEC);
struct epoll_event event;
int ctl_ret;
event.events = EPOLLIN;
event.data.fd = STDIN_FILENO;
ctl_ret = epoll_ctl(fd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
if (ctl_ret) {
perror("epoll_ctl");
return 1;
}
int nr_event;
for (;;) {
fprintf(stderr, "Starting epoll_wait\n");
nr_event = epoll_wait(fd, &event, 1, -1);
if (nr_event < 0) {
perror("epoll_wait");
return 1;
}
fprintf(stderr, "Reading: %d\n", event.data.fd);
printf("%ld\n", read(0, buffer, sizeof(buffer)));
}
}
As Basile Starynkevitch alluded to, I needed to update the terminal configuration via termios(3) .正如 Basile Starynkevitch 提到的,我需要通过termios(3)更新终端配置。
I have provided the revised code below for reference.我在下面提供了修改后的代码以供参考。 For the changes required, please see the code between the
// TERMINAL SETUP
and // EPOLL SETUP
comments.对于所需的更改,请参阅
// TERMINAL SETUP
和// EPOLL SETUP
注释之间的代码。
#include <errno.h>
#include <linux/input.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <termios.h>
#include <unistd.h>
int main(void) {
// TERMINAL SETUP
struct termios tty_cfg, tty_cfg_cache;
// Check that fd is a TTY
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "Standard input is not a terminal.\n");
return EXIT_FAILURE;
}
// Save old terminal configuration
if (tcgetattr(STDIN_FILENO, &tty_cfg_cache) == -1 ||
tcgetattr(STDIN_FILENO, &tty_cfg) == -1) {
fprintf(stderr, "Cannot get terminal settings: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
// Set new terminal configuration
tty_cfg.c_iflag &= ~(IGNBRK | BRKINT | PARMRK);
tty_cfg.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN | TOSTOP);
tty_cfg.c_cc[VMIN] = 0;
tty_cfg.c_cc[VTIME] = 0;
tty_cfg.c_cc[VSTART] = 0;
tty_cfg.c_cc[VSTOP] = 0;
if (tcsetattr(STDIN_FILENO, TCSANOW, &tty_cfg) == -1) {
const int saved_errno = errno;
tcsetattr(STDIN_FILENO, TCSANOW, &tty_cfg_cache);
fprintf(stderr, "Cannot set terminal settings: %s.\n", strerror(saved_errno));
return EXIT_FAILURE;
}
// EPOLL SETUP
// Create epoll
int epfd = epoll_create1(EPOLL_CLOEXEC);
// Add stdin control interface to epoll
struct epoll_event event;
int ctl_ret;
event.events = EPOLLIN;
event.data.fd = STDIN_FILENO;
ctl_ret = epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
if (ctl_ret) {
perror("epoll_ctl");
return 1;
}
// LOOP AND MONITOR EPOLL
int nr_event;
unsigned char keys[16];
ssize_t n;
size_t i, done;
done = 0;
while (!done) {
// Start epoll_wait
nr_event = epoll_wait(epfd, &event, 1, -1);
if (nr_event < 0) {
perror("epoll_wait");
return 1;
}
// Read STDIN_FILENO
n = read(STDIN_FILENO, keys, sizeof keys);
if (n > 0) {
for (i = 0; i < n; i++) {
// Quit if 'q' or 'Q' is pressed
if (keys[i] == 'q' || keys[i] == 'Q')
done = 1;
if (keys[i] >= 32 && keys[i] <= 126)
printf("Key '%c' = 0x%02x = %u pressed\n", keys[i], keys[i], keys[i]);
else
if (keys[i])
printf("Key '\\%03o' = 0x%02x = %u pressed\n", keys[i], keys[i], keys[i]);
else
printf("NUL key (0) pressed\n");
}
fflush(stdout);
}
}
// RESTORE TERMINAL SETTINGS
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty_cfg_cache);
return EXIT_SUCCESS;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.