簡體   English   中英

為什么 epoll_wait 不響應終端輸入?

[英]Why is epoll_wait not responding to terminal input?

以下代碼在運行時不響應終端輸入。 我在 Debian 10.5.0 和 CentOS 7 下運行它,結果相同。 我錯過了什么?

#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)));
    }

}

正如 Basile Starynkevitch 提到的,我需要通過termios(3)更新終端配置。

我在下面提供了修改后的代碼以供參考。 對於所需的更改,請參閱// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM