Linux下read函数详解
在Linux中,read 函数是最常用的系统调用之一,用于从文件或其他输入设备读取数据。它是低级别的I/O操作的核心,直接与操作系统的内核交互,提供了高效的数据读取方式。
一、read 函数简介
read 函数的声明如下:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
其中:
fd是文件描述符,代表了需要读取的文件或设备。文件描述符可以通过调用open或其他文件操作函数获取。buf是一个指向用户分配的缓冲区的指针,read将把读取到的数据写入该缓冲区。count是需要读取的字节数,表示最多读取count字节数据。
返回值:
- 若成功,
read返回读取的字节数(0表示已到达文件末尾)。 - 若失败,返回
-1,并设置errno来指示具体错误。
二、read 函数的工作原理
read 函数是一个阻塞调用,意味着如果请求的数据还没有准备好,它会使调用的进程挂起,直到有数据可读或发生错误。内核根据文件描述符查找到对应的文件系统对象,执行相应的读取操作。以下是其工作流程的简要概述:
- 获取文件描述符:文件描述符是打开文件时分配的,它是内核中维护文件表的索引。
- 检查文件状态:内核会检查文件描述符是否有效,文件是否已打开,并且具有读权限。
- 读取数据:从文件或设备中读取数据,并将其复制到用户提供的缓冲区
buf中。 - 返回结果:返回读取的字节数,若遇到错误则返回
-1,并通过errno提供错误信息。
文件末尾的处理
当到达文件末尾时,read 会返回 0,表示没有更多的数据可读。这是进程得知文件已经读取完毕的信号。
三、常见的用法
read 函数经常与 open、close 以及其他系统调用一起使用。以下是一个简单的示例,它展示了如何从文件中读取数据:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {int fd;ssize_t bytesRead;char buffer[1024]; // 定义一个缓冲区用于存储读取的数据// 打开文件fd = open("example.txt", O_RDONLY);if (fd == -1) {perror("Failed to open file");return 1;}// 读取数据bytesRead = read(fd, buffer, sizeof(buffer) - 1);if (bytesRead == -1) {perror("Failed to read file");close(fd);return 1;}// 确保字符串末尾以 '\0' 结束buffer[bytesRead] = '\0';// 输出读取到的数据printf("Read %zd bytes: %s\n", bytesRead, buffer);// 关闭文件close(fd);return 0;
}
在该示例中:
- 使用
open以只读模式打开文件。 - 调用
read将文件的内容读取到buffer中。 - 读取后输出数据,并在最后调用
close关闭文件。
四、错误处理
read 调用可能会因为多种原因失败,一些常见的错误包括:
EINTR:调用被信号中断。EIO:发生I/O错误(如硬件故障)。EINVAL:参数不合法,比如文件描述符不是合法的读取对象。EBADF:文件描述符无效,可能因为文件未打开或者以不适合的方式打开(如只写模式下无法读取)。EFAULT:缓冲区地址不合法。
在编写系统级程序时,必须对这些错误进行适当的处理。通常,在每次 read 调用后检查返回值是否为 -1,并根据 errno 来做出相应的处理决策。
五、非阻塞读取
read 默认是阻塞的,即当数据不可用时会阻塞进程。然而,可以使用 O_NONBLOCK 标志将文件或设备设置为非阻塞模式。当文件描述符以非阻塞模式打开时,若数据不可用,read 将立即返回 -1,并设置 errno 为 EAGAIN 或 EWOULDBLOCK。
示例如下:
fd = open("example.txt", O_RDONLY | O_NONBLOCK);
if (fd == -1) {perror("Failed to open file in non-blocking mode");return 1;
}bytesRead = read(fd, buffer, sizeof(buffer));
if (bytesRead == -1 && errno == EAGAIN) {printf("No data available yet, try again later.\n");
}
六、与缓冲区的关系
read 函数直接与内核缓冲区交互。文件系统通常维护一个内核缓冲区,用于缓存文件数据,以减少磁盘 I/O 操作的次数。read 调用从内核缓冲区中读取数据到用户空间,若缓冲区为空,则从磁盘或设备读取数据到缓冲区。
在设计高性能系统时,选择适当的缓冲区大小非常重要。过小的缓冲区会导致频繁的系统调用,从而影响性能;而过大的缓冲区则会消耗过多的内存。
七、read 在不同设备中的应用
read 不仅适用于文件操作,还可以用于读取设备、管道、套接字等。以下是几种常见应用场景:
1. 从标准输入读取
可以使用文件描述符 0 来从标准输入读取数据:
ssize_t bytesRead = read(0, buffer, sizeof(buffer));
2. 从管道读取
在进程间通信中,管道也是常见的数据传输方式,read 可用于从管道中读取数据:
int pipefd[2];
pipe(pipefd);
read(pipefd[0], buffer,sizeof(buffer));
3. 从套接字读取
read 也可以用于从网络套接字中读取数据,这在基于网络的编程中非常有用:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
read(sockfd, buffer, sizeof(buffer));
八、总结
read 函数是Linux系统编程中最基础和重要的系统调用之一,它为从文件、设备、管道或网络套接字读取数据提供了直接的接口。在编写基于Linux的应用程序时,充分理解 read 的工作机制、错误处理和性能考虑,对于编写高效、健壮的代码至关重要。
相关文章:
Linux下read函数详解
在Linux中,read 函数是最常用的系统调用之一,用于从文件或其他输入设备读取数据。它是低级别的I/O操作的核心,直接与操作系统的内核交互,提供了高效的数据读取方式。 一、read 函数简介 read 函数的声明如下: #inclu…...
【二叉树遍历算法应用】------补录
0.二叉树结点的链式存储结构 #include<stdio.h> #include<stdlib.h> #include<stdbool.h>typedef char TElemType;//树中元素基本类型为char类型//二叉树结点链式存储结构(二叉链表) typedef struct BiNode {TElemType data;//数据域…...
AtCoder Beginner Contest 368
A.Cut(模拟) 题意: 有一叠 N N N张扑克牌,最上面的 i i i张扑克牌上写着一个整数 A _ i A\_i A_i。 你从牌堆底部取出 K K K张牌,将它们放在牌堆顶部,并保持它们的顺序。 操作后从上到下输出写在卡…...
WebGL系列教程六(纹理映射与立方体贴图)
目录 1 前言2 思考题3 纹理映射介绍4 怎么映射?5 开始绘制5.1 声明顶点着色器和片元着色器5.2 修改顶点的颜色为纹理坐标5.3 指定顶点位置和纹理坐标的值5.4 获取图片成功后进行绘制5.5 效果5.6 完整代码 6 总结 1 前言 上一讲我们讲了如何使用索引绘制彩色立方体&a…...
为什么nii.gz转.nrrd标签体积变大?
import SimpleITK as sitk # nii nii.gz nrrd格式之间互相转换 def nii2nii(oripath, savepath):data sitk.ReadImage(oripath)img sitk.GetArrayFromImage(data)out sitk.GetImageFromArray(img)sitk.WriteImage(out, savepath)if __name__ __main__:oripath 00292625.ni…...
软件安装攻略:EmEditor编辑器下载安装与使用
EmEditor是一款在Windows平台上运行的文字编辑程序。EmEditor以运作轻巧、敏捷而又功能强大、丰富著称,得到许多用户的好评。Windows内建的记事本程式由于功能太过单薄,所以有不少用户直接以EmEditor取代,emeditor是一个跨平台的文本编辑器&a…...
Redis的watch机制详解
WATCH 是 Redis 提供的一个用于实现 乐观锁 (Optimistic Lock) 的命令,通常用于实现事务中的并发控制。它允许客户端监控一个或多个键的变化,并确保事务(MULTI/EXEC)中执行的操作在这些键没有发生改变的情况下才能成功提交。若在事…...
UnrealEngine 打包Android平台应用
虚幻引擎 支持将项目发布到 安卓(Android) 移动设备上,并且提供了若干功能帮你将项目发布到 谷歌游戏商店。本节包含了如何设置Android开发环境、如何使用Android功能和服务、以及如何为发布游戏做准备相关的指南。 当前SDK要求 当前UE版本…...
Linux:git
hello,各位小伙伴,本篇文章跟大家一起学习《Linux:git》,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 ! 如果本篇文章对你有帮助,还请各位点点赞!!&…...
electron有关mac构建
针对 Mac M1/2/3 芯片的设备,proces.archarm64. 执行下面命令,检查下按照的 node.js 版本是不是 intel x64 指令集,如果是的话安装下 arm64 指令集的 node.js终端中执行以下命令:node -p process.arch 对应的node版本也是arm版 …...
C语言-数据结构 弗洛伊德算法(Floyd)邻接矩阵存储
弗洛伊德算法相比迪杰斯特拉相似的地方都是遍历邻接矩阵不断调整最短路径的信息,并且两种算法面对多源最短路径的时间复杂度都是O(n^3),Floyd采用的是动态规划而Dijkstra是采用贪心的思想。在Floyd中我们将创建两个数组进行辅助,一个path二维…...
pyspark 安装记录
1、安装软件 1、python 3.10 2、hadoop-3.3.4 里面的winutils 要记得添加 3、java-17 4、spark-3.5.1-bin-hadoop3 python 安装 pyspark,Jupyter notebook pip install pyspark pip install jupyter notebook 2、添加环境变量 JAVA_HOME=C:\PySparkService\java-17H…...
高度可定制的电竞鼠标,雷柏VT1 PRO MAX体验
不管是菜鸟还是老鸟,游戏玩到某个阶段很容易出现瓶颈,在游戏的某个阶段,这里面制约最大的除了操作之外,实际上还是我们用的硬件。比如在PC游戏中,鼠标的影响就非常大,像是在游戏中如果鼠标延迟过高…...
经验笔记:SOA(面向服务的架构)
SOA(面向服务的架构)经验笔记 引言 SOA(Service-Oriented Architecture, 面向服务的架构)是一种设计原则,用于构建灵活且可扩展的分布式系统。SOA强调将应用程序的不同功能封装为独立的服务,这些服务通过…...
triton之ttir学习
一 基本语句 1 常量 %cst arith.constant dense<520192> : tensor<4096xi32> %c127_i32 arith.constant 127 : i32 %cst arith.constant dense<520192> : tensor<4096xi32> 解释:这条语句定义了一个名为 %cst 的常量,它…...
如何在AWS账户上进行充值:一份详尽指南
大家好,小编今天给大家带来一份关于如何在AWS账户上进行充值的详尽指南。对于使用AWS服务的用户来说,保持账户余额充足是确保服务不中断的关键。下面,九河云将详细讲解具体的操作步骤。 步骤一:登录AWS管理控制台 首先ÿ…...
(六十四)第 10 章 内部排序(静态链表的插入排序)
示例代码 staticLinkList.h // 静态链表的插入排序实现头文件#ifndef STATIC_LINK_LIST_H #define STATIC_LINK_LIST_H#include "errorRecord.h"#define SIZE 100 #define NUM 8typedef int InfoType; typedef int KeyType;typedef struct {KeyType key;InfoType inf…...
appium历史版本地址链接
appium / Appium.app / Downloads — Bitbucket ios的appium界面图 链接: https://pan.baidu.com/s/1i8BRaZgQA3ImLUhKZjfhiA 提取码: 5c8b...
TCPIP网络编程(尹圣雨)UDP 轮流收发消息(windows)
端口号写的是 2345 客户端 #include <iostream> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib")using std::cout; using std::endl; using std::cin;int main() {WSADATA wsa;if (WSAStartup(MAKEWORD(2, 2), &wsa) ! 0){cout <<…...
【相机方案(2)】V4L2 支持相机图像直接进入GPU内存吗?DeepStream 确实可以将图像数据高效地放入GPU内存进行处理!
V4L2 支持相机图像直接进入GPU内存吗? V4L2(Video4Linux Two)是Linux内核中用于视频捕获和播放的API,它本身并不直接支持将相机捕获的图像数据直接拷贝到GPU内存而不经过CPU内存。V4L2主要关注于视频设备的控制、数据的捕获和播放…...
给SAP财务新人的年结实操笔记:从FAGLGVTR总账结转到F.07往来结转,一次讲清
SAP财务年结实战指南:从总账到往来的完整逻辑解析 刚接触SAP财务模块的新人面对年结时,往往会被一连串的事务代码和操作步骤弄得晕头转向。FAGLGVTR、AJRW、F.07这些看似冰冷的代码背后,其实蕴含着清晰的财务逻辑。本文将带你穿透操作表象&am…...
XCOM 2模组管理终极解决方案:AML启动器效率革命指南
XCOM 2模组管理终极解决方案:AML启动器效率革命指南 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/…...
避坑指南:STM32磁编码器校准常见的5个错误及解决方案
STM32磁编码器校准实战:5个典型错误分析与高阶解决方案 磁编码器在步进电机控制系统中扮演着关键角色,而MT6816作为国产AMR技术代表芯片,其14位高精度输出为位置检测提供了可靠保障。但在实际校准过程中,开发者常会遇到CALI_Error…...
手把手教你优化SiC MOSFET模块:从铜带键合到双面散热的5个关键技术
SiC MOSFET功率模块封装优化实战:五大关键技术深度解析 在电力电子领域,碳化硅(SiC)MOSFET功率模块正逐步取代传统硅基IGBT,成为高效率、高功率密度应用的首选。然而,要充分发挥SiC材料的性能优势,封装技术面临前所未…...
保姆级教程:深求·墨鉴Podman部署全流程,小白也能轻松搞定
保姆级教程:深求墨鉴Podman部署全流程,小白也能轻松搞定 1. 为什么选择Podman部署深求墨鉴? 传统Docker部署方式虽然常见,但对于深求墨鉴这样的轻量级OCR工具来说,Podman提供了更优雅的解决方案。Podman是一款无需守…...
通义千问3-Reranker-0.6B实战应用:智能客服问答排序系统搭建
通义千问3-Reranker-0.6B实战应用:智能客服问答排序系统搭建 1. 智能客服问答排序系统概述 在智能客服系统中,如何从海量知识库中快速找到最匹配用户问题的答案,是提升用户体验的关键。传统基于关键词匹配的方法往往难以理解用户真实意图&a…...
yz-bijini-cosplay真实案例:COSER试装前预览、服装打样视觉参考图
yz-bijini-cosplay真实案例:COSER试装前预览、服装打样视觉参考图 1. 项目概述 yz-bijini-cosplay是一个专为RTX 4090显卡优化的Cosplay风格文生图系统,基于通义千问Z-Image底座和专属LoRA权重开发。这个系统能够帮助COSER在试装前预览效果,…...
Kronos金融市场基础模型:从技术原理到量化交易系统构建
Kronos金融市场基础模型:从技术原理到量化交易系统构建 【免费下载链接】Kronos Kronos: A Foundation Model for the Language of Financial Markets 项目地址: https://gitcode.com/GitHub_Trending/kronos14/Kronos 金融市场的复杂性和波动性一直是投资者…...
为什么92%的Java边缘项目因Classloader泄漏失败?揭秘3层隔离沙箱设计与实时热替换机制
第一章:Java边缘计算轻量级运行时开发概览边缘计算场景对运行时环境提出严苛要求:低内存占用(通常 ≤ 64MB)、毫秒级冷启动、有限依赖、原生支持资源约束设备(如 ARM64 IoT 网关、工业 PLC)。Java 生态传统…...
别再让UI卡死了!WPF开发中Dispatcher.Invoke和BeginInvoke的保姆级避坑指南
别再让UI卡死了!WPF开发中Dispatcher.Invoke和BeginInvoke的保姆级避坑指南 当你在WPF应用中点击一个按钮后界面突然冻结,进度条卡在50%不再前进,鼠标变成旋转的沙漏——这种糟糕的用户体验往往源于错误的线程调度方式。作为C#开发者…...
