Linux系统层IO

1.c语言文件操作

fopen:打开文件,模式 "w"(写,覆盖)或 "r"(读)。

fwritefwrite(data, size, count, fp),按 size 字节写入 count 次数据。

freadfread(buf, size, count, fp),返回实际读取字节数,需结合 feof 处理文件结束。

fclose:关闭文件,释放资源,必须调用以避免泄漏。

1.打开关闭文件:

#include <stdio.h>int main() {FILE *fp = fopen("myfile", "w");if (!fp) {printf("fopen error!\n");}while (1); // 死循环,fclose无法执行fclose(fp);return 0;
}

2.写文件:

#include <stdio.h>
#include <string.h>int main() {FILE *fp = fopen("myfile", "w");if (!fp) {printf("fopen error!\n");return 1;}const char *msg = "hello bit!\n";for (int i = 0; i < 5; ++i) { // 更清晰的循环fwrite(msg, strlen(msg), 1, fp);}fclose(fp);return 0;
}

3.读文件:

#include <stdio.h>
#include <string.h>int main() {FILE *fp = fopen("myfile", "r");if (!fp) {printf("fopen error!\n");return 1;}char buf[1024];const char *msg = "hello bit!\n"; // 正确定义指针(原代码可能笔误,此处修正)size_t read_len = strlen(msg); // 12字节while (1) {ssize_t s = fread(buf, 1, read_len, fp); // 每次读取12字节if (s > 0) {buf[s] = '\0'; // 终止字符串printf("%s", buf);}if (feof(fp)) { // 检查文件结束break;}}fclose(fp);return 0;
}

更加细节的操作,可以再C语言文件操作-CSDN博客文章中查看

stdin &stdout& stderr

C默认会打开三个输入输出流,分别是stdin,stdout,stderr仔细观察发现,

这三个流的类型都是FILE*,fopen返回值类型,文件指针

2.系统文件I/O

认识一下两个概念:系统调用和库函数
上面的 fopen fclose freadfwrite 都是C标准库当中的函数,我们称之为库函数(libc)。
而 open close read write lseek 都属于系统提供的接口,称之为系统调用接口

 

不管是c c++ 还是java 所有的语言对文件的操作的库函数,其实都是系统IO套了一层语言的外壳

2.1.系统文件的接口

1.打开文件open:

打开或创建文件,返回文件描述符。

有两种创建方式:
第一种:就是文件已经存在的情况

第二种:就是文件如果不存在,那么就其文件进行创建,mode参数就是设置创建文件的权限

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>4 int open(const char *pathname, int flags);
5 int open(const char *pathname, int flags, mode_t mode);6
7 pathname: 要打开或创建的目标文件
8 flags: 打开文件时,可通过“或”运算组合多个常量,规则如下:
9 参数:
10     基本模式(必选其一,互斥):
11         O_RDONLY:只读(0)
12         O_WRONLY:只写(1)
13         O_RDWR  :读写(2)
14         三者必选且仅选其一
15     附加标志(可选,| 组合):
16         O_CREAT :创建文件(需配mode,不存在则建,存在则按基本模式打开)
17         O_APPEND:追加写(指针移到末尾,不覆盖原有内容)
18         O_TRUNC :写模式下截断文件(清空内容,覆盖写入,与O_APPEND互斥)
19         O_EXCL   :与O_CREAT联用,确保文件不存在(存在则失败,errno=EEXIST,原子创建)
20         O_NONBLOCK:非阻塞IO(设备/套接字操作不阻塞,立即返回,需处理EAGAIN)
21         O_SYNC   :同步写(数据+元数据立即刷盘,保证持久,性能开销大)
22         O_DIRECT :直接IO(绕过内核缓冲,需内存/偏移对齐,否则EINVAL)
23 mode: 仅O_CREAT时有效,指定新文件权限(如0644),实际权限为mode & ~umask24 返回值:
25     成功: 非负文件描述符(如3,4...,0/1/2为标准IO)
26     失败: -1(检查errno,用perror调试,如ENOENT(文件不存在)、EEXIST(O_CREAT+O_EXCL冲突)等)

2.写文件write:

向文件写入缓冲区数据。

3.读文件read:

关闭文件描述符,释放资源。

上面三种接口都使到标志位,那么下面就是识别标志位的一种方式:

上面参数flags传递标志位的方法:

采用的的位图的思想,只需要判断对应的二进制位上是否是1即可

2.1.文件描述符fd

理解文件描述符之前先了解fd代表什么,又是存储在哪里?

一个进程都有PCB,在PCB中,有个指针数组*files 表示一个进程可以管理多个文件,而指针数组*files 的下标就是我们说的fd ,files[fd]:就是指向下标为fd的文件,系统会自动的的打开三个文件,分别是 标准输入,标准输出,标准错误,他们对应的下标是 0,1,2

以上原理结论我们可通过内核源码验证:

2.1.1.文件描述符的分配规则

在files_struct数组当中,找到 当前没有被使⽤的最⼩的⼀个下标,作为新的⽂件描述符
1.没有将系统自动打开的三个文件关闭,自动排在,下标为三的位置。

2.此时将0和1下标的文件关闭,发现打印的0;

2.1.2.重定向

明白了上面的规则后,看一个现象:

当我们将标准输出给关闭,printf向输出文件写东西的时候,发现内容没有写到标准输出文件,而写到了新创建的文件

原理:

输出到了⽂件 ll 当中,其中,fd=1。这 种现象叫做输出重定向。常⻅的重定向有: > , >> , <
也说明了,语言层的库函数只认fd

使用dup2 系统调用:

函数原型:

再看一个示例:发现此时的fd 和 1指向的都是新创建的ll 文件

3.一切皆文件

首先,在windows中是文件的东西,它们在linux中也是文件;其次一些在windows中不是文件的东西,比如进程、磁盘、显示器、键盘这样硬件设备也被抽象成了文件,你可以使用访问文件的方法访问它们获得信息;甚至管道,也是文件;


这样做最明显的好处是,开发者仅需要使用一套 API和开发工具,即可调取 Linux 系统中绝大部分的资源。举个简单的例子,Linux中几乎所有读(读文件,读系统状态,读PIPE)的操作都可以用read 函数来进行;几乎所有更改(更改文件,更改系统参数,写PIPE)的操作都可以用 write 函数来进行。

4.缓冲区

缓冲区的定义:

缓冲区是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

在不同层面上也是分成 :

用户级:语言层缓冲区

语言层的缓冲区内容就缓冲到文件内核缓冲区

系统层: 文件内核缓冲区

文件内核缓冲区内容就缓冲到磁盘中

缓冲区的作用:

读写文件时,如果不会开辟对文件操作的缓冲区,直接通过系统调用对磁盘进行操作(读、写等),那么每次对文件进行一次读写操作时,都需要使用读写系统调用来处理此操作,即需要执行一次系统调用,执行一次系统调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现进程上下文的切换,这将损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率造成很大的影响。


为了减少使用系统调用的次数,提高效率,我们就可以采用缓冲机制。比如我们从磁盘里取信息,可以在磁盘文件进行操作时,可以一次从文件中读出大量的数据到缓冲区中,以后对这部分的访问就不需要再使用系统调用了,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

这时我们的CPU可以处理别的事情。可以看出,缓冲区就是块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

4.1.缓冲类型

缓冲区类型分成下面三种:
 

全缓冲区:

这种缓冲方式要求填满整个缓冲区后才进行1/0系统调用操作。对于磁盘文件的操作通常使用全缓冲的方式访问。

原本标准输出是行缓冲区,但是已经重定向到了“log.txt”文件,所以变成了全缓冲区,所以要使用语言层的刷新函数fflush进行刷新


行缓冲区:

在行缓冲情况下,当在输入和输出中遇到换行符时,标准I/0库函数将会执行系统调用操作。当所操作的流涉及一个终端时(例如标准输入和标准输出),使用行缓冲方式。因为标准I/0库每行的缓冲区长度是固定的,所以只要填满了缓冲区,即使还没有遇到换行符,也会执行/O系统调用操作,默认行缓冲区的大小为1024。

原本标准输出是行缓冲区,但是已经重定向到了“log.txt”文件,所以变成了全缓冲区,所以没有数据刷新到文件缓冲区

无缓冲区:

无缓冲区是指标准I/0库不对字符进行缓存,直接调用系统调用。标准出错流stderr通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。

标准错误就是无缓冲区:

4.2.FILE

观察此段代码:

运行结果1:

运行结果2(对进程实现输出重定向 ./hello > file):

重定向结果解析:

1.当重定向的时候,缓冲区的缓冲方式已经变成了从行缓冲变成了全缓冲。

2.所以msg0和msg1写在了用户级的缓冲区,msg3调用的是系统IO,所以直接写在,内核缓冲区中。

3.fork()创建子进程,所以父子进程都结束的时候,对进行二次对用户级的缓冲区的刷新

4.所以此时打印的是这种结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92555.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT中的trimmed() 方法(1)

QT中的trimmed() 方法&#xff08;2&#xff09; trimmed() 是 Qt 框架 中 QString 类提供的一个方法&#xff0c;用于 去除字符串首尾的空白字符&#xff08;whitespace characters&#xff09;。它的作用类似于标准 C 中的 std::string 的 trim 操作&#xff0c;但专为 Qt 的…

动漫软件集合分享

通过网盘分享的文件&#xff1a;动漫软件 链接: https://pan.baidu.com/s/1TD_OmaAZksfFxJ4PW6rS-w?pwd1234 提取码: 1234 打印动漫.apk 当鸟动漫.apk 动漫共和国【OmoFun复活】.apk 咕咕香.apk 黑猫动漫.apk 团次元【推荐】.apk 橘漫.apk 曼波.apk 萌国.apk 趣动漫.apk 三…

Mysql与Ooracle 索引失效场景对比

MySQL 和 Oracle 作为主流关系型数据库&#xff0c;其索引失效的场景既有共性&#xff0c;也因底层优化器、索引类型支持等差异存在不同。以下从常见索引失效场景对比两者的表现及原因&#xff1a;一、索引列上使用函数 / 表达式共性&#xff1a;若直接在索引列上使用函数或表达…

【unity知识】unity使用AABB(轴对齐包围盒)和OBB(定向包围盒)优化碰撞检测

文章目录前言一、AABB&#xff08;轴对齐包围盒&#xff09;1、基本概念2、数学表示3、Unity中的实现4、实际应用示例二、OBB&#xff08;有向包围盒&#xff09;1、Physics.ComputePenetration (Unity 物理引擎)1.1 基本概念1.2 Unity中的实现1.3 实际应用示例2、OBB (SAT) 手…

Numpy科学计算与数据分析专题

Numpy科学计算与数据分析 1. Numpy入门&#xff1a;数组操作与科学计算基础 2. Numpy入门&#xff1a;多平台安装与基础环境配置 3. Numpy数组创建与应用入门 4. Numpy数组属性入门&#xff1a;形状、维度与大小 5. Numpy数组索引与切片入门 6. Numpy数组操作入门&#xff1a;…

齐护机器人小智AI_MCP图形化编程控制Arduino_ESP32

齐护机器人小智AI_MCP图形化编程控制Arduino_ESP32 齐护AiTall在项目实践里&#xff0c;我们常常期望达成这样一种场景&#xff1a;借助智能体&#xff08;例如小智 AI&#xff09;来远程操控其他开发板上的设备&#xff0c;这类似于智能家居系统中智能音箱与各类家电的互动模式…

CPO-SVM分类预测+特征贡献SHAP分析,通过特征贡献分析增强模型透明度,Matlab代码实现,引入SHAP方法打破黑箱限制,提供全局及局部双重解释视角

代码功能 该Matlab代码实现了一个基于CPO-SVM冠豪猪算法优化支持向量机的数据分类模型&#xff0c;结合了SHAP可解释性分析&#xff0c;CPO选择最佳的SVM参数c和g。 SVM模型有两个非常重要的参数C与gamma。其中 C是惩罚系数&#xff0c;即对误差的宽容度。c越高&#xff0c;说明…

Failed to restart docker.service: Unit docker.service is masked.

docker.service 被标记为 "masked" 意味着 systemd 已阻止该服务被启动或运行。这通常发生在 Docker Desktop 安装过程中,因为它使用自己的服务管理机制。以下是解决方法: 解决方案: 解除服务的 mask 状态: bash sudo systemctl unmask docker.service sudo sys…

2025 蓝桥杯C/C++国B 部分题解

P12836 [蓝桥杯 2025 国 B] 翻倍 题目描述 给定 nnn 个正整数 A1,A2,…,AnA_1, A_2, \ldots, A_nA1​,A2​,…,An​&#xff0c;每次操作可以选择任意一个数翻倍。 请输出让序列单调不下降&#xff0c;也就是每个数都不小于上一个数&#xff0c;最少需要操作多少次&#xff1f;…

os标准库

os标准库os包提供了操作系统函数&#xff0c;但和操作系统无关。 os包的接口规定为在所有操作系统中都是一致的。 设计为Unix风格的。1. 权限说明 os标准库有大量的文件操作&#xff0c;在创建文件等操作中&#xff0c;需要指的perm。 在go语言中perm是一个uint32类型 在go语言…

QtC++ 中使用 qtwebsocket 开源库实现基于websocket的本地服务开发详解

前言 当前实时通信功能越来越受到重视&#xff0c;无论是在线聊天、实时数据监控还是多人协作工具&#xff0c;都离不开高效、稳定的实时通信技术。WebSocket 作为一种全双工通信协议&#xff0c;为实时通信提供了良好的解决方案。而在 QtC 开发环境中&#xff0c;qtwebsocket …

小程序实时保存优化

背景。避免数据存储后丢失。要求实时保存。问题&#xff1a;保存时出现卡断&#xff0c;输入的内容会被抹除。问题原因。输入频繁速度块&#xff0c;会影响cpu处理速度。解决方案。用户停止输入500ms后开始保存&#xff0c;否则不保存。这里是保存方法&#xff1a;当500ms以内有…

国产化Excel处理组件Spire.XLS教程:使用 C# 将 DataTable 导出为 Excel 文件

在 C# 中将 DataTable 导出为 Excel 文件&#xff0c;是 .NET 开发中常见的任务&#xff0c;广泛应用于报表生成、日志导出、系统间数据共享等场景。通过使用独立的组件库&#xff0c;开发者可以轻松将 DataTable 数据写入 Excel 文件&#xff0c;并应用格式设置&#xff0c;生…

C语言学习笔记——编译和链接

目录1 C程序的执行流程2 翻译环境2.1 预编译2.2 编译2.2.1 词法分析2.2.2 语法分析2.2.3 语法分析2.3 汇编2.4 链接1 C程序的执行流程 用户编写好的C程序不能直接被计算机识别并执行&#xff0c;在执行前&#xff0c;要先将源文件和头文件进行编译&#xff0c;生成目标文件&am…

Flink-1.19.0源码详解9-ExecutionGraph生成-后篇

《Flink-1.19.0源码详解8-ExecutionGraph生成-前篇》前篇已从Flink集群端调度开始解析ExecutionGraph生成的源码&#xff0c;解析了ExecutionGraph的ExecutionJobVertex节点、ExecutionVertex节点、IntermediateResult数据集、IntermediateResultPartition数据集分区与封装Task…

19、阈值分割+blob分析

目录 一、仿射变换 1.变换矩阵 2.在矩阵的基础上添加各种变换形式 3.开始变换 4.计算变换矩阵参数 新算子 二、阈值分割 新算子 三、blob分析案例 1.焊点 2.石头 3.木材 4.车牌 5.骰子 新算子 一、仿射变换 1.变换矩阵 // 产生仿射变换矩阵hom_mat2d_identity…

破解 Django N+1 查询困境:使用 select_related 与 prefetch_related 实践指南

破解 Django N+1 查询困境:使用 select_related 与 prefetch_related 实践指南 开篇引入 数据库查询性能常常是 Web 应用性能瓶颈中的重中之重。Django ORM 以简洁直观的 API 层将 Python 代码与数据库打通,却也可能因默认的惰性加载带来 N+1 查询问题,造成不必要的网络往…

深入解析K-means聚类:从原理到调优实战

一、聚类分析与K-means的核心价值在无监督学习领域&#xff0c;聚类分析是探索数据内在结构的核心技术。​K-means算法因其简洁高效成为最广泛使用的聚类方法&#xff0c;在客户分群、图像压缩、生物信息学等领域应用广泛。其核心目标是将数据集划分为K个簇&#xff0c;实现“簇…

数据结构基础:哈希表、排序和查找算法

目录 一、哈希表 1.哈希算法 2.哈希碰撞 3.哈希表 4.哈希表相关操作 哈希表插入 哈希表遍历 元素查找 哈希表销毁 二、排序算法 1. 排序算法对比 2. 排序算法实现 冒泡排序 选择排序 插入排序 希尔排序 快速排序 三、查找算法 1. 查找算法对比 2. 查找算法实…

Linux内核参数调优:为K8s节点优化网络性能

在高并发微服务环境中&#xff0c;网络性能往往成为K8s集群的瓶颈。本文将深入探讨如何通过精细化的Linux内核参数调优&#xff0c;让你的K8s节点网络性能提升30%以上。引言&#xff1a;为什么网络调优如此重要&#xff1f;作为一名在生产环境中维护过数千节点K8s集群的运维工程…