读取标准输入非阻塞

Read stdin non-blocking

我正在编写一个 Vala 程序,它作为 child_process 使用标准输出和标准输入与父级进行消息传输。在异步方法中,我调用 read_stdin(sb) 来检查传入消息。我尝试了各种标准输入方法,如 gets 和 getc,但它们似乎都在 '\n' 换行符上阻塞。我需要立即读取所有可用字符和 return(非阻塞)。

    const int STDIN_BUF_SIZE=1024;
    char[] stdin_buffer;
    bool read_stdin (StringBuilder sb) {
        int iPos=0;
        int c;
        int buf_size=STDIN_BUF_SIZE-1;
        // Char by char:
        while (true) {
            c = stdin.getc ();
            if(c ==  GLib.FileStream.EOF) break;
            stdin_buffer[iPos]=(char)c;
            iPos++;
            if ((char)c=='\n'||iPos==buf_size){
                break;
                }
            }
        if(iPos>0){
            stdin_buffer[iPos]=0;
            sb.append((string)stdin_buffer);
            return true;
            }
        return false;
    }

stdin 可以用于非阻塞 IO 还是我需要创建类似...

DataInputStream stdin_reader = new DataInputStream(stdin);

您使用了 "non-blocking" 这个词,但我认为这不是您认为的意思。如果非阻塞 I/O 是您真正想要的,那么用 O_NONBLOCK 打开 /dev/stdin 会很容易。在这种情况下,getc 会立即 return EOF 直到有数据可用。

AFAICT,您实际上想要的是 getc 调用阻塞,直到有新数据可用,然后立即 return。从技术上讲,这就是正在发生的事情。问题是终端应用程序通常会缓冲数据直到出现换行符,这就解释了为什么您可以编辑数据但应用程序不会看到任何编辑内容;继续,尝试在您的程序中输入 "AB",您将看到的将是 "B\n".

基本上,你需要使用一个curses library。 Vala 包含一个 curses.vapi,因此您只需要 link 到相关库(可能是 ncurses)并将 --pkg curses 添加到您的 valac 调用中,您就可以了走。 IIRC 相关函数是 getch,但我在 时间里没有做过任何 curses 编程。