代码之家  ›  专栏  ›  技术社区  ›  Smashery

非阻塞标准

  •  3
  • Smashery  · 技术社区  · 15 年前

    我正在开发一个程序,它将从控制台接收用户输入,并在单独的线程中打印输出。我希望避免这样的情况:用户在输入内容的中途出现printf并在光标处打印自己。

    有没有办法从控制台窗口在c中执行非阻塞io?理想情况下,捕捉按键或类似的东西,这样用户键入的内容就不会出现在屏幕上。我在Ubuntu上开发,最好不用像ncurses这样的东西。

    3 回复  |  直到 15 年前
        1
  •  4
  •   dfa    15 年前

    使用 termios 您可以禁用终端回音:

    #include <termios.h>
    
    struct termios oflags, nflags;
    tcgetattr(fileno(stdin), &oflags);
    nflags = oflags;
    nflags.c_lflag &= ~ECHO;
    nflags.c_lflag |= ECHONL;
    
    if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
        /* handle error */
    }
    

    然后在退出之前(使用 atexit )必须还原终端:

    if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
        /* handle error */
    }
    
        2
  •  2
  •   Mark Rushakoff    15 年前

    下面是一个如何从C关闭echo的示例,直接从 an HP forum (我还没有亲自测试过):

    好的,这应该是一个简单的例子 关闭回声的方法:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <termios.h>
    
    #define STDIN_FDES 0
    
    struct termios save;
    
    int main(int argc, char *argv[])
    {
    int cc = 0;
    char s_tmp[80],*p = NULL;
    struct termios work;
    
    cc = tcgetattr(STDIN_FDES,&save);
    work = save;
    work.c_lflag &= ~(ECHO);
    cc = tcsetattr(STDIN_FDES,TCSANOW,&work);
    (void) printf("\nEnter value: ");
    (void) fflush(stdout);
    p = fgets(s_tmp,sizeof(s_tmp),stdin);
    if (p != NULL) (void) printf("Out -> %s\n",p);
    cc = tcsetattr(STDIN_FDES,TCSANOW,&save);
    return(cc);
    }
    

    SIGTERM。。。重置终端 因为 最后一个tcsetttr()获胜,这适用于 回音关闭,它将在壳中关闭 也。

    否则,如果Bash是一种合适的方法,显然您可以这样做 stty -echo

        3
  •  0
  •   Jim Lewis    15 年前

    如果我正确理解了您的问题,那么关闭echo或使用非阻塞I/O不是答案。相反,您希望防止后台线程中断用户输入线程,对吗?

    为此,您需要访问原始按键,而不是行缓冲输入。我不知道你为什么对网络课程或类似的图书馆过敏,那就是它们的用途!我想你可以用termios或者ioctl电话,如果你是这样的话。。。。

    1) 创建一个mutex来控制谁可以访问控制台

    ,以输出消息:

    在用户输入线程中:

    检测到新输入时获取互斥锁。保持独占访问,直到用户按enter键, 然后释放互斥量并给背景线程一个对话的机会。