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

       由于最近在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; 
}


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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值