select() on stdin when there is already data in stdin's buffer

The select function blocks the calling process until there is activity on any of the specified sets of file descriptors [...] A file descriptor is considered ready for reading if a read call will not block. (See: https://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html)

So I expected, that select in the following program would immediately return in the 2nd, ... iteration, if you enter a string > 4 characters in the first iteration. However it does not. Just after pressing any other key after the first output it continues to handle all the remaining input. Why?

Sample output:

./selectTest
12345678900
Keyboard input received: 1234
A
Keyboard input received: 5678
Keyboard input received: 900

Keyboard input received: A

Code

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main(void)
{
    fd_set rfds;
    char buf[100];

    while(1)
    {
        FD_ZERO(&rfds);       
        FD_SET(fileno(stdin), &rfds);

        if(-1 == select(FD_SETSIZE, &rfds, NULL, NULL, NULL))
        {
            perror("select() failedn");
        }

        if(FD_ISSET(fileno(stdin), &rfds)) 
        {
            printf("Keyboard input received: ");
            fgets(buf, 5, stdin);
            printf("%sn", buf);
        }
    }
    return 0;
}

(I know, that I should not use select() anymore, but I am learning for an exam and we have to ...)


You are reading from a tty(4) (in the usual case when stdin is your terminal). These are tricky things, read the tty demystified.

Be aware that your terminal and its tty has some line discipline. So, some data is buffered in the kernel (and also in the standard library).

You might want to put your tty in raw mode. See termios(3) & stty(1)

But don't lose your time, instead use some library like ncurses or readline

To play with select , you might use some fifo(7), perhaps with mkfifo /tmp/myfifo then yourprogram < /tmp/myfifo and, in another terminal, echo hello > /tmp/myfifo


Fundamentally, the problem is that you're mixing buffered stdio streams with low-level I/O. The reason the select is blocking is because the previously typed data has already been read and is buffered in stdin 's stream data buffer. Try setting stdin to unbuffered mode by calling setbuf(stdin, NULL) .

链接地址: http://www.djcxy.com/p/68804.html

上一篇: 在Xcode GUI中指定构建操作(例如安装)

下一篇: 当标准输入缓冲区中已有数据时,在标准输入上选择()