Linux下非阻塞读取键值的实现

来源:互联网 发布:网络机顶盒av口接音箱 编辑:程序博客网 时间:2024/06/06 08:58

       由于最近在Gstreamer下编写各种插件(如http,hls等),需要实现在点播过程中,可以随时监测键值从而实现退出、暂停的功能,而且监测键值是非阻塞的,不会影响到视频播放正常退出。

      基于这样一个需求,上网查询资料,发现有两种方法来实现。


1) 可以将监测键值单独放在一个线程中进行,设置非阻塞模式read()或者getchar()等。

  设置非阻塞方式为:fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK);

  若按键并未按下,则会立即返回,并不会占用CPU资源;

  若有按键按下,判断是否为‘q’,若是则退出播放。


2) 在linux下实现windows中kbhit的功能

声明:该部分参考http://hi.baidu.com/jtntiivtemcnsue/item/90689ce172ee912c5a7cfb1b


/* init_keyboard与close_keyboard在程序的开始和结束配置终端 */

函数tcgetattr具体用法:

http://baike.baidu.com/view/5644808.htm

函数tcsetattr具体用法:

http://baike.baidu.com/view/8022475.htm


#include <stdio.h>#include <termios.h>#include <term.h>#include <unistd.h>void init_keyboard(){    tcgetattr(0,&initial_settings);  /* get stdin(fd=0) parameter and store into init.. */    new_settings = initial_settings;    new_settings.c_lflag &= ~ICANON; /* use the standard input style */    new_settings.c_lflag &= ~ECHO;   /* display the input char */    new_settings.c_lflag &= ~ISIG;   /* when input INTR/QUIT/SUSP/DSUSP, send associated signal */    new_settings.c_cc[VMIN] = 1;     /* read the min num of char is 1 */    new_settings.c_cc[VTIME] = 0;    tcsetattr(0, TCSANOW, &new_settings); /* set the attr of terminal */}void close_keyboard(){    tcsetattr(0, TCSANOW, &initial_settings);}



/* 实现kbhit的功能,若有键值按下则返回1,同时将键值压入stdin中;若无键值按下,则返回0 */

int kbhit(void)  {      struct termios oldt, newt;      int ch;      int oldf;      tcgetattr(STDIN_FILENO, &oldt);      newt = oldt;      newt.c_lflag &= ~(ICANON | ECHO);      tcsetattr(STDIN_FILENO, TCSANOW, &newt);          /* set the nonblock */    fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK);      ch = getchar();      tcsetattr(STDIN_FILENO, TCSANOW, &oldt);      fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0));      if (ch != EOF)      {          ungetc(ch, stdin);  /* back the ch to stdin */        return 1;      }      return 0;  }  


/* 配置好终端以及实现非阻塞监测键值之后,在主函数中调用即可。

注意:由于该功能实现不能影响到后续程序的运行,且它是一个事件(event)触发的函数,只有当监测到按键按下时,才运行该kbhit函数。其他时候,程序是不在此中运行的。*/

int main(void)  {      int ch;    while (TURE)    {        if ((ch = getchar()) != NULL) /* 如果没有这个判断,按下按键是无法监测到的,也就是进不了kbhit函数 */        {                       if (kbhit())          /* 经过测试,发现getchar()那里依然是非阻塞形式,无法自动退出 */            {                if ('q' == ch)                {                     printf("Prapare to quit!\n");                    break;                 }            }        }        /* other codes */        ...    }     return 0; }


最后,还是决定由多线程来实现键值的读取。经测试成功。





原创粉丝点击