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主要关注于视频设备的控制、数据的捕获和播放…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
