linux下实现键盘的非阻塞输入

    最近遇到一个需求:linux下的程序在忽略其他退出信号的情况下,按q键退出。
    由于主线程需要监听键盘输入,正常情况读取字符串会阻塞,导致主线程无法正常退出,因此考虑用非阻塞的形式实现。
    在linux下每打开一个终端,系统自动的就打开了三个文件,它们的文件描述符分别为0,1,2,功能分别是“标准输入”、“标准输出”和“标准错误输出”,同时对应了三个文件流指针,分别是stdin,stdout和stderr。

使用ioctl清除非阻塞标志

函数原型:

int ioctl(int d, int request, …);

参数:

d:文件描述符

request:功能码。根据填写的功能码选择第三个参数。

返回:

成功返回0,失败返回-1。

ioctl函数传入的第二个参数为FIONBIO表示“设置/清除非阻塞标志”,那么第三个参数要传入一个int类型的指针,指针指向的值为1表示设置非阻塞标志,那么对应的文件描述符为非阻塞,指针指向的值为0表示清除非阻塞标志,那么对应的文件描述符为阻塞。
  因此调用如下代码即可实现非阻塞:

int attr = 1;
ioctl(STDIN_FILENO, FIONBIO, &attr);   /* 清除非阻塞标志 */

完整代码如下:

// 处理中途退出程序
    char buf[128] = { 0 };
    int len = 0;
    int total = 0;
    int attr = 1;
    ioctl(STDIN_FILENO, FIONBIO, &attr);   /* 清除非阻塞标志 */
    printf("input 'q' to quit \n");
    while (!read_quit || !send_quit)
    {
        len = read(STDIN_FILENO, &buf[total], sizeof(buf) - total);
        //printf("len = %d\n", len);
        if (len > 0) {
            total += len;
            if (buf[total - 1] == '\n') {
                //printf("total = %d\n", total);
                //printf("buf = %s\n", buf);
                if (buf[0] == 'q') 
                {
                    //退出处理
                    break;
                }
                total = 0;
                memset(buf, 0, sizeof(buf));
            }
        }
        msleep(2000);
    }
    //退出时记得恢复阻塞输入
    attr = 0;
    ioctl(STDIN_FILENO,FIONBIO,&attr);//attr为0

你可能感兴趣的:(c++,linux,c++)