相关文章推荐
寂寞的红薯  ·  autojs切换窗口-掘金·  1 年前    · 
爱看球的围巾  ·  java - jdk keytool ...·  1 年前    · 
聪明的墨镜  ·  testing - Channel ...·  1 年前    · 
踏实的水煮鱼  ·  mysql导入oracle ...·  1 年前    · 

Linux环境下使用fcntl实现C语言非阻塞输入

在使用C语言编程时,常常会用到 scanf() getchar() 等函数来获取键盘的输入,当键盘没有输入时程序会发生阻塞并一直保持在阻塞状态,此时如果想要继续执行下一步的程序,就需要将IO状态置为非阻塞,以确保无用户输入的情况下程序的正常执行。

fcntl 是Linux中的函数,用来改变已打开文件的性质,其定义为 int fcntl(int fd, int cmd); ,其中参数 fd 表示欲设置的文件描述符,参数 cmd 代表将要执行的操作,如果该操作需要键入参数, fcntl 能够接收第三个参数 int arg 。返回值与命令相关,如果出错,所有命令都返回-1,如果成功则返回某个其他值。

用法举例:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
    int flag1, flag2;
    if(flag1=(fcntl(STDIN_FILENO, F_GETFL, 0)) < 0)
        perror("fcntl");
        return -1;
    flag2 = flag1 | O_NONBLOCK;
    fcntl(STDIN_FILENO, F_SETFL, flag2);
    int a, ret;
    while(1)
        sleep(2);
        int ret = scanf("%d", &a);
        if(ret >= 0)
            printf("%d\n", a);
            printf("--------------\n");
    return 0;

运行以上程序得到的输出效果为:

ubuntu@ubuntu:~/Desktop$ ./a.out 
--------------
--------------
2  # 这个2为获取键盘输入
--------------
--------------
--------------

IO设置为非阻塞状态后,可以通过修改程序使其恢复到阻塞状态:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
    int flag1, flag2;
    if(flag1=(fcntl(STDIN_FILENO, F_GETFL, 0)) < 0)
        perror("fcntl");
        return -1;
    flag2 = flag1 | O_NONBLOCK;
    fcntl(STDIN_FILENO, F_SETFL, flag2);
    int a, ret;
    while(1)
        sleep(2);
        int ret = scanf("%d", &a);
        if(ret >= 0)
            printf("%d\n", a);
            printf("--------------\n");
            fcntl(STDIN_FILENO, F_SETFL, flag1);
    return 0;

此时的效果为:

ubuntu@ubuntu:~/Desktop$ ./a.out 
--------------
  # 此时光标一直停留,直至获取到键盘输入
这样就对文件test加锁了,如果有其他进程对test文件加锁,则不能成功,会被阻塞,但不会退出程序。
解锁:fcntl.flock(f,fcntl.LOCK_UN)
fcntl模块:
flock() : flock(
                                    C语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 FCNTLC语言头文件 F
                                    一、基础研究要从地址读取数据,肯定是要定义一个指针变量p,用它来实现变换地址和取值的功能。另外程序是当两个条件中的某一个出现时才停止,所以应该用while~do循环语句循环输出n和d,并用while进行判断。这里实现三个问题:(1)循环地把值转换成地址。(2)判断偏移地址是否为0xffff。(3)判断用户是否输入了‘q’。前两个问题比较好实现,对于第三个问题我们需要注意的是c语言是怎么处理用户输入...
                                    《跟我学Linux编程-5-非阻塞式键盘输入》由会员分享,可在线阅读,更多相关《跟我学Linux编程-5-非阻塞式键盘输入(2页珍藏版)》请在人人文库网上搜索。1、今天的课题再回到键盘输入使用scanf()从键盘读取格式化输入信息,大家肯定都用得非常好;相信有些同志也有过getchar()函数,从键盘读取单个字符。无论是scanf还是getchar,被大家有时候所诟病的是,它们通常都是阻塞式的,...
                                    非阻塞I/O使我们的操作要么成功,要么立即返回错误,不被阻塞。
对于一个给定的描述符两种方法对其指定非阻塞I/O:
(1)调用open获得描述符,并指定O_NONBLOCK标志
(2)对已经打开的文件描述符,调用fcntl,打开O_NONBLOCK文件状态标志。
flags = fcntl( s, F_GETFL, 0 ) )
fcntl( s, F_SETFL, flags | O_NONBLOCK )
                                    #include "../include/CommUart.h"#include"ComCommon.h"#include#include#include#include#include#include#include#includeusing namespacestd;#define USR_DEBUGstatic structtermios ori_attr, cur_attr;static ...
                                    #include "windows.h"#include "process.h"#include "stdio.h"#define BUFFER_MAX 1024char g_nbstdin_buffer[2][BUFFER_MAX];HANDLE g_input[2];HANDLE g_process[2];DWORD WINAPI console_input(LPVOID lpParamete...
                                    一、Windows中的非阻塞式监听实现
所谓键盘监听,就是用户按下某个键时系统做出相应的处理,本章讲到的输入输出函数也是键盘监听函数的一种,例如 getchar()、getche()、getch() 等。下面的代码演示了 getche() 函数的使用:
#include <stdio.h>
#include <conio.h>
int main(){
    char...
                                    每一位代表一个文件描述符,  为了监控每个文件描述符,又开辟了一个fd_set类型数组,将fd_set集合中要监控的数组位置设置为1,监控的文件描述符放入集合里面,1024/8,每位表示一个文件描述符,新开辟的数组可以监控多少个文件描述符1024/8,这样算下来还是有些多了。FD_ZERO()清除集合里面的数据,FD_SET()把关心的fd加入集合,FD_CLR()从集合中清除fd,FD_ISSET()判断fd是否在set中。注意:select退出后,集合是有数据的集合(关心的数据已经加入集合)
                                    C语言每日一练 2021年11月7日———实现无阻塞读取按键———分析:kbhit()是一个C和C++函数,用于非阻塞地响应键盘输入事件,为 “keyboard hit(键盘敲击)”的简写。kbhit是 _kbhit() 的弃用别名,尽管它依然受到支持,微软仍建议使用遵循 C 命名规则的 _kbhit()。