【Linux】C语言系统函数实现阻塞和非阻塞读取终端

Linux环境下使用fcntl实现C语言非阻塞输入 Linux环境下使用fcntl实现C语言非阻塞输入 在使用C语言编程时,常常会用到scanf()、getchar()等函数来获取键盘的输入,当键盘没有输入时程序会发生阻塞并一直保持在阻塞状态,此时如果想要继续执行下一步的程序,就需要将IO状态置为非阻塞,以确保无用户输入的情况下程序的正常执行。 fcntl是Linux中的函数,用来改变已打开文件的性质,其定义为int fcntl(int fd, int cmd);,其中参数fd表示欲设置的文件描述符,参数cmd代表将要执行的操作,如果该操作需要键入参数,fc 阅读详情

 🔥博客主页: 我要成为C++领域大神

🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】

❤️感谢大家点赞👍收藏⭐评论✍️

本博客致力于分享知识,欢迎大家共同学习和交流。

从常规文件读取不会阻塞;无论读取多少数据,read 函数都会在有限的时间内返回。

从终端设备或网络读取可能会阻塞。例如,如果从终端输入的数据缺少换行符,则调用终端设备的 read 函数会阻塞。如果网络上没有接收到数据包,则调用网络的 read 函数会阻塞。至于阻塞的持续时间是不确定的。如果没有数据到达,进程将会无限期地保持阻塞状态。

“阻塞”:当进程调用一个阻塞的系统函数时,它会进入睡眠(sleep)状态,此时内核会调度其他进程运行,直到等待的事件发生(比如在网络上收到数据包,或者等待指定的sleep睡眠时间结束),进程才会继续执行。睡眠状态的相对状态是运行(Running)状态。在 Linux 内核中,运行状态的进程分为两种情况:

  1. 主动调度执行:CPU 正在执行进程的指令,读写其地址空间,并在通用寄存器中保存中间结果。
  2. 就绪状态:进程随时可以执行,但当前 CPU 正在执行另一个进程。因此,进程在就绪队列中等待内核调度。系统中可能同时有多个就绪的进程。内核的调度算法基于优先级和时间片,动态调整每个进程的优先级和时间片,以确保公平执行,并响应用户交互。

下面我们将用read,write,fcntl函数实现阻塞和非阻塞读取终端

read

1、功能:
read 函数用于从已打开的设备或文件中读取数据。

2、头文件:
read 函数的声明位于 <unistd.h> 头文件中。

3、函数定义:

ssize_t read(int fd, void *buf, size_t count);


这是 read 函数的函数原型,它接受三个参数:文件描述符 fd、存储读取数据的缓冲区地址 buf 和要读取的字节数 count。

4、返回值:
read 函数的返回值是 ssize_t 类型,表示成功读取的字节数。如果出错,则返回 -1,并设置全局变量 errno 指示错误类型。如果在调用 read 前已经到达文件末尾,则返回 0。

5、参数说明:

fd:要读取的文件的文件描述符,它是通过 open 等函数打开文件时返回的。

buf:要将读取的数据存储到哪个缓冲区中,这个缓冲区通常是一个指向数据的指针。

count:请求读取的字节数,读取到的数据将会保存到缓冲区 buf 中,并且文件的当前读写位置会向后移动相应的字节数。

write

1、功能:
write 函数用于从打开的设备或文件中写入数据。

2、头文件:
write 函数的声明位于 <unistd.h> 头文件中。

3、函数定义:

ssize_t write(int fd, const void *buf, size_t count);


这是 write 函数的函数原型,它接受三个参数:文件描述符 fd、要写入的数据缓冲区地址 buf 和要写入的字节数 count。

4、返回值:
write 函数的返回值是 ssize_t 类型,表示成功写入的字节数。如果出错,则返回 -1,并设置全局变量 errno 指示错误类型。如果在调用 write 之前已经到达文件末尾,则 write 返回 0。

5、参数说明:

fd:要写入的文件的文件描述符,它是通过 open 等函数打开文件时返回的。

buf:存储要写入内容的缓冲区的地址,这个缓冲区可以是任何内存中的位置,通常是一个指向数据的指针。

count:请求写入的字节数,将要写入的数据保存在缓冲区 buf 中,并移动文件的当前读写位置。

fcntl

1、功能:
fcntl 函数用于对文件描述符进行控制操作,包括复制描述符、获取/设置文件描述符标志以及获取/设置文件状态标志等。

2、头文件:
fcntl 函数的声明位于 <fcntl.h> 头文件中。

3、函数定义:

int fcntl(int fd, int cmd, ... /* arg */ );


fcntl 函数接受三个参数:文件描述符 fd、控制命令 cmd 以及可选的参数 arg。
当函数有两个参数时,是获取权限;
当函数有三个参数时,是设置权限

4、返回值:
fcntl 函数的返回值根据不同的命令而异。一般情况下,成功执行时返回值取决于命令的具体含义,失败时返回 -1,并设置全局变量 errno 指示错误类型。

5、参数说明:

fd:要操作的文件的文件描述符。

cmd:控制命令,用于指定要执行的操作。常见的命令包括:

F_DUPFD:复制文件描述符。

F_GETFL:获取文件描述符的标志。

F_SETFL:设置文件描述符的标志。

F_GETFD:获取文件状态标志。

F_SETFD:设置文件状态标志。

等等,还有其他命令用于进行不同的操作。

arg:可选参数,用于传递给指定命令的参数。具体参数类型和含义取决于命令。

函数实现:

阻塞读取:

阻塞读取不需要使用fcntl函数改变标准输入符权限,因为本身标准输入本身就是阻塞的。

将标准输入读取到的数据写入到标准输出即可。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{

    char buf[10] = "";
    int nLength = read(STDIN_FILENO, buf, sizeof(buf));
    write(STDOUT_FILENO, buf, nLength);
    return 0;
}

阻塞读取标准输入,当读取到标准输入按下回车后,程序结束的速度很快

                                      

非阻塞读取:

非阻塞读取需要使用fcntl函数改变标准输入符权限为非阻塞。

1、fcntl获取标准输入权限

2、设置标准输入权限为非阻塞

3、读取标准输入

4、写入到标准输出中去

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

int main()
{
    // 获取当前标准输入权限
    int flags = fcntl(STDIN_FILENO, F_GETFL);
    // 改变当前标准输入权限为非阻塞
    flags |= O_NONBLOCK;
    char buf[10] = "";
    int nLength;
    while (1)
    {
        nLength = read(STDIN_FILENO, buf, sizeof(buf)); // 读取标准输入
        if (nLength == -1)
        {
            if (errno == EAGAIN)
            {             // 没有读取到数据
                sleep(1); // 等待一秒,再重新读
                continue;
            }
            else
            { // 文件读取失败
                perror("read fail");
                return -1;
            }
        }
        else
        {
            break; // 读取成功,退出循环
        }
    }
    write(STDOUT_FILENO, buf, nLength); // 写入到标准输出中去
    return 0;
}

非阻塞读取标准输入,当读取到标准输入按下回车后,有时程序退出比较慢,因为可能出去非阻塞的sleep时间。

openssl 使用非阻塞 bio 在 openssl 中使用非阻塞的bio方法纪要。通过与 epoll 的配合,完成高效的加密连接处理 阅读详情

相关推荐

C/C++中open函数的阻塞和非阻塞编程

阻塞模式会在open函数调用处等待文件打开完成,而非阻塞模式会立即返回,并在文件无法立即打开时设置errno为EAGAIN或EWOULDBLOCK。当read或write函数在非阻塞模式下读取或写入文件时,如果没有可用数据或无法立即写入,这些函数也会返回-1,并设置errno为EAGAIN或EWOULDBLOCK。open函数可以以阻塞或非阻塞的方式打开文件,这取决于对文件描述符的标志位进行的设置。当以阻塞模式打开文件时,程序会在open函数调用处等待,直到文件打开操作完成。

PixelInk的博客 785

终极版C语言(十三)

整个教程以 C++ 语言为核心,完整精彩的演练了数据结构、算法、设计模式、数据库、大数据高并发检索、文件重定向、多线程同步、进程通讯、黑客劫持技术、网络安全、加密解密,以及各种精彩的小项目等,非常适合大家学习。讲课生动风趣、深入浅出,全套视频内容充实。

【LinuxC语言】阻塞、回调与轮询快速理解

在Linux C语言编程中,阻塞、回调和轮询是三种常见的处理输入/输出(I/O)的方式。这些方法在处理网络通信、多线程编程和套接字编程等场景中都有广泛的应用。理解这三种方法的工作原理和使用场景,对于提高编程效率和程序性能至关重要。阻塞、回调和轮询各有优缺点,适用于不同的场景。阻塞模式简单直观,但可能导致程序在等待I/O操作完成时无法进行其他任务。轮询模式可以避免阻塞,但需要不断检查I/O状态,可能会浪费CPU资源。

m0_62599305的博客 461

c语言 阻塞函数协程,协程 | 易学教程

1.携程的概念# 进程 资源分配的最小单位# 线程 CPU执行的最小单位​# 只要是线程里的代码 就都被CPU执行就行# 线程是由 操作系统 调度,由操作系统负责切换的# 协程: # 用户级别的,由我们自己写的python代码来控制切换的 # 是操作系统不可见的# 在Cpython解释器下 - 协程和线程都不能利用多核,都是在一个CPU上轮流执行 # 由于多线程本身就不能利用多核...

weixin_33980343的博客 938

Linux:阻塞/非阻塞读终端

阻塞读终端:block指当串口输入缓冲区没有数据的时候,read函数将会阻塞在这里,移植到串口输入缓冲区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数 #include <unistd.h> #include <stdlib.h> int main(void) { char buf[10]; int n; n = read(STDIN_FILE...

不秃头的程序猿Gabriel的博客 797

Linux网络编程(阻塞和非阻塞)

errno.h>是一个非常有用的头文件,它提供了一种标准化的方式来处理程序运行时的错误。通过errno变量、错误码宏、以及perror和strerror函数,程序员可以轻松地检测和报告错误,从而更好地调试和维护代码。

m0_49476241的博客 1652

18 Linux 阻塞和非阻塞 IO

概念:阻塞和非阻塞,一个是在内核里面,一个是在内核和用户空间反复跳。他们的概念需要知道。阻塞:当一个任务或线程执行某个操作时,如果该操作无法立即完成,任务或线程将会被阻塞(暂停执行)。阻塞式会一直占用 CPU,直到操作完成,这里面有 等待队列头,等待队列项,等待唤醒和等待事件比较重要。非阻塞:当一个任务或线程执行某个操作时,如果该操作无法立即完成,任务或线程不会被阻塞,而是立即返回,继续执行后续的任务或代码。非阻塞式调用不会一直占用 CPU 资源,任务或线程可以在等待操作完成时去处理其他任务或代码。

Toutiegongzhu的博客 1335

【高等数值分析】Krylov子空间方法

文章目录1. 预备理论1.1 Krylov 子空间1.2 最佳逼近1.2.1 方法一:最佳平方逼近1.2.2 方法二:假设 AAA 对称正定1.2.3 方法三:残差2范数2. 基底正交化2.1 Arnoldi 过程(CGS)2.2 改进 Arnoldi 过程(MGS)2.3 Lanczos过程3. 方程组求解3.1 全正交方法 (FOM)3.2 D-Lanczos方法3.3 广义极小残量法(GMRES)3.4 MINRES 方法 1. 预备理论 现在需要求解一个大规模稀疏方程组 Ax=bAx=bAx=b,可

Glooow的博客 1万+

linux c实现超时、非阻塞socket的函数select

linux c实现超时、非阻塞socket的函数select Select在Socket编程中还是比较重要的,可是对于初学Socket的人来 说都不太爱用Select写程序,他们只是习惯写诸如 connect、accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等  待某个事件的发生,如果事件没有

tjssehaige的专栏 1万+

【异常】Claude Code 在 Windows CMD 中出现重影现象的排查与解决

Windows CMD运行Claude Code时出现文字重影、乱码等问题,原因是传统CMD对现代ANSI终端控制序列支持不足。解决方案包括:1)推荐安装Windows Terminal(完全支持ANSI标准);2)使用PowerShell 7;3)优化CMD设置(启用虚拟终端、UTF-8编码);4)关闭Claude Code视觉特效。建议优先使用Windows Terminal以获得最佳体验,这是最彻底的解决方案。其他方案仅能部分改善或缓解问题。

奶爸的编程之路,也就一周冷个三天 1961

Python爬虫实战:微信小程序内容采集的全面指南

在移动互联网时代,微信小程序已成为企业和个人提供服务的重要渠道。小程序中包含了大量有价值的信息,但微信官方并未提供便捷的数据获取接口。本文将详细介绍如何使用Python爬虫技术采集微信小程序内容,包括最新技术方案、完整代码实现以及应对各种反爬机制的策略。小程序运行在微信封闭环境中,无法直接访问数据通信主要通过HTTPS加密传输内容动态加载,依赖JavaScript渲染微信有严格的反爬机制。

2201_76125261的博客 3116

Linux 使用fcntl c_cc[VMIN] c_cc[CTIME]设置串口阻塞与非阻塞读取数据

一、概述 Linux串口非常灵活,可以根据需要配置成标准串口和自定义串口模式,就Linux 串口读取数据来说,有有两种主要方式:阻塞与非阻塞。 阻塞:一直等待数据,直到退出条件成立; 非阻塞:及时返回当前数据,不管有无均退出。 这里的退出条件有数据等待时间间隔、需要读取的字节数等。例如,有以下两种串口场景使用场景,请进行配置: 非阻塞方式,及时返回当前完整数据包。 固定200ms的时间等...

健忘16的博客 4955

杰理SDK入门教程(五):按键使用配置

摘要 杰理SDK提供IO按键和AD按键两种方案。IO按键通过GPIO电平检测实现,配置时需要设置板级宏定义和硬件连接,默认使用PB1引脚。AD按键基于ADC电压采样,通过电阻分压区分按键,需配置功能使能、硬件通道和键值适配。按键功能通过修改SDK中的key_table文件实现。两种方案适用于不同硬件场景,开发者可根据需求选择。

qq_42014563的博客 776

【Linux】五种IO模型 + 非阻塞IO

【Linux】非阻塞IO

tan_run的博客 1568

几种负载均衡策略(DNS、NAT、重定向、反向代理)

摘要:本文对比了四种负载均衡技术:DNS负载均衡通过域名解析分发IP,用户直连服务器;NAT负载均衡通过VIP转发流量,所有流量经过负载均衡器;HTTP重定向通过302跳转实现分流;反向代理则隐藏后端服务器,统一转发请求。DNS简单但调度不精准,NAT精准但有带宽瓶颈,HTTP重定向延迟高,反向代理性能好但需专用设备。适用场景各异,DNS适合异地分流,NAT适合内网集群,HTTP重定向适合简单分流,反向代理适合高并发场景。核心区别在于层级(3层/7层)和流量走向(直连/中转)。

echo的博客 71

《手把手教你玩转RTOS操作系统》专栏简介

《手把手教你玩转RTOS操作系统》专栏系统讲解实时操作系统开发,以FreeRTOS为主线,结合RT-Thread和Zephyr对比分析。内容涵盖RTOS基础、任务管理、通信机制、中断处理等核心知识,并配套STM32/ESP32平台实战项目。专栏特色在于零基础友好、实战驱动、多系统对比和行业趋势分析,适合嵌入式开发者进阶RTOS开发能力,解决实际项目中的选型与优化问题。通过完整学习路径,读者可掌握构建高可靠性嵌入式系统的关键技能。

MHD0815的博客 531

非阻塞轮询

watipid 系统调用中的options 参数 以及 非阻塞轮询的同时是如何执行其它任务的。

CPPER 2659

基于GA-BP遗传算法优化神经网络的多输入多输出数据预测-Python代码实现

多输入多输出的GA-BP神经网络

2301_80449389的博客 2308

Linux下非阻塞读操作

#include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #define MSG_TRY "try again\n" #define MSG_TIMEOUT "timeout\n" // 非阻塞读终端和等待超时 int main(int

嵌入式 1674

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

linux下串口的阻塞和非阻塞操作

有两个可以进行控制串口阻塞性(同时控制read和write):一个是在打开串口的时候,open函数是否带O_NDELAY;第二个是可以在打开串口之后通过fcntl()函数进行控制。 阻塞的定义:        对于read,block指当串口输入缓冲区没有数据的时候,read函数将会阻塞在这里,移植到串口输入缓冲区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数;

wulonghui123的博客 5729

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

linux read函数非阻塞,C/C++ open函数的阻塞和非阻塞

调用open函数时,可以指定是以阻塞方式还是以非阻塞方式打开一个文件描述符。阻塞方式打开:int fd = open("/dev/tty", O_RDWR|O_NONBLOCK);非阻塞方式打开:int fd = open("/dev/tty", O_RDWR);例子:#include #include #include #include #include int main(int argc, c...

weixin_39612220的博客 1961

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

初识Linux · 五种IO模型和非阻塞IO

前文我们已经将网络的基本原理介绍完了,都是通过围绕TCP/IP四层协议,将应用层,传输层,网络层,数据链路层全部介绍完毕,至于部分小主题,比如ARP欺骗,HTTP协议的原理,cookie以及session等内容,我们放在后面介绍。本文以及之后的内容,主要通过是介绍IO相关的问题,通过IO模型的介绍,从而引出多路复用的具体内容,通过介绍select,poll,epoll,最后再单独介绍一下Reactor,网络的基本原理我们就介绍完了。那么废话不多说,我们直接进入五种IO模型。

更新各种计算机技能~ 1265

Linux终端游戏开发:用kbhit()实现非阻塞键盘输入检测(附完整代码)

本文详细介绍了在Linux终端游戏开发中,如何通过实现kbhit()函数来解决阻塞式输入难题,实现非阻塞键盘输入检测。文章从原理出发,提供了完整的C语言代码示例,并构建了一个简易游戏框架,帮助开发者创建实时响应的终端游戏。

threejs5artist的博客 1078

c语言 linux scanf非阻塞输入,linux C之getchar()非阻塞方式

#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 ...

weixin_33910305的博客 776

【Linux-阻塞,非阻塞,异步】

Linux-Linux-阻塞和非阻塞 IO■ Linux-阻塞■ Linux-非阻塞 IO ■ Linux-阻塞 ■ Linux-非阻塞 IO

sinat_23896491的博客 336
上一篇: 【力扣】回文链表
下一篇: 【力扣】课程表
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值