【Linux】基础 IO(一)

📝前言:

这篇文章我们来讲讲Linux——基础IO主要包括:

  1. 文件基本概念
  2. 回顾 C文件的操作
  3. 介绍系统关于文件的基本操作

🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏


目录

  • 一,基本概念
    • 1. 概念
    • 2. 系统角度
  • 二,C 文件的 IO
    • 1. 打开操作
    • 2. 写操作
    • 3. 读操作
    • 4. 默认打开的流
  • 三,系统文件的 IO
    • 1. 位标记传递
    • 2 系统调用 open
    • 3 读写的系统调用
      • 使用示例
      • 库函数和系统调用
    • 4 文件描述符(重点)
      • 文件描述符的分配原则

一,基本概念

1. 概念

  • 狭义:
    • 文件在磁盘上
    • 磁盘是永久性存储物质
    • 磁盘是外设,即是输入设备,也是输出设备
    • 对文件的操作,其实是对外设的输入和输出,称为 IO
  • 广义:
    • Linux 下⼀切皆文件
    • 文件 == 内容 + 属性

2. 系统角度

  • 对⽂件的操作本质是进程对⽂件的操作
  • 硬件(如磁盘)的管理者是操作系统
  • ⽂件的读写本质不是通过 C 语⾔ / C++ 的库函数来操作的(这些库函数只是为用户提供⽅便),底层是通过文件相关的系统调用接口来实现的

二,C 文件的 IO

1. 打开操作

fopen

  • FILE *fopen(const char *pathname, const char *mode);
    • pathname:文件路径
    • mode:打开方式
  • 返回:
    • 成功:返回文件指针
    • 失败:返回NULL

这个FILE的类型是一个文件结构体,通过typedef来的。这是语言层的。

2. 写操作

写操作,在文件不存在的时候都会创建文件。

打开文件时的写入模式:

  • 清空写w:清空文件内容,重新写
  • 追加写a:在原来文件内容后面追加写

fwrite

  • size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    • ptr的数据写到stream
    • size:每个数据项的大小,比如写intsiezeof(int)(就是4
    • nmemb:数据项的个数
  • 返回:实际成功写入的数据项数量

注意:文件写入的时候不能写入'\0''\0'是C语言的东西,写入了以后是乱码

示例:

  5 // C 语言文件接口回顾6 int main()7 {8     FILE* fp1 = fopen("log1.txt", "w");9     FILE* fp2 = fopen("log2.txt", "a");10     if(fp1 == NULL) printf("log1.txt 打开失败\n");11     if(fp2 == NULL) printf("log2.txt 打开失败\n");12     char* str1 = (char *)"测试写入\n";13     fwrite(str1, strlen(str1), 1, fp1);14     fwrite(str1, strlen(str1), 1, fp2);15     fclose(fp1);16     fclose(fp2);17     return 0;18 } 

当使用相对路径的时候,进程通过自己记录的自己工作路径CWD信息,知道新建的文件要放在哪里

运行结果:
在这里插入图片描述

3. 读操作

读操作,如果文件不存在会报错
fread

  • size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    • 不解释了,和fwrite的都一样,不一样的就是stream是读入的流,ptr是存储读入数据的地方。
    • 在上一次读取结束后文件指针的位置继续读取。
  • 返回:实际成功读取的数据项数量

示例:

 20 int main()21 {22     FILE* fp = fopen("log2.txt", "r");23     if(fp == NULL) printf("打开文件失败");24 25 26     char* str1 = (char *)"测试写入\n";27     char buff[1024];28     while(1)29     {30         // 这里每次读都是覆盖写buff的,但是我们及时打印出来                                                                                                                                                  31         int s = fread(buff, 1, sizeof(str1), fp); // 这里每次读一个char,方便后续设置 '\0'32         if(s > 0)33         {34             buff[s] = 0;35             printf("%s", buff);36         }37         if(feof(fp))38             break;39     }40     return 0;41 }

运行结果:
在这里插入图片描述

4. 默认打开的流

#include <stdio.h>
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;

C默认会打开三个输⼊输出流,分别是标准输入:stdin, 标准输出:stdout, 标准错误:stderr

三,系统文件的 IO

头文件:<unistd.h>

1. 位标记传递

利用位图进行标记位传递,假设,现有标记位:ONE : 0001TWO:0010THREE:0100

  • 如果我们单独传入一个ONE就相当于传递了最低位的1
  • 如果我们希望传递第最低位的1和次低位的1,就可以传入ONE | TWO(通过获的方式)

2 系统调用 open

系统,通过系统调用open打开文件:
在这里插入图片描述

  • pathname:文件路径
  • falgs:选项(约等于C语言里面的打开模式),通过 或|来实现传递多个选项【这个选项本质是宏实现的标记位】
  • 常见选项:
    • O_RDONLY:只读打开
    • O_WRONLY: 只写打开
    • O_RDWR : 读,写打开
  • 上面这三个常量,必须指定⼀个且只能指定⼀个。
  • 其他选项
    • O_CREAT :若文件不存在,则创建它。需要使用mode选项(传入3个8进制数字),来指明新文件的访问权限。如果新建的时候,不传入,那对应的文件就是乱码【别忘了实际的权限要考虑umask的影响】
    • O_TRUNC:清空写
    • O_APPEND:追加写
  • 返回值
    • 成功:新打开的文件的文件描述符(系统通过这个来找到需要访问的文件)
    • 失败:-1

3 读写的系统调用

在这里插入图片描述
write

  • 参数
    • fd:文件描述符
    • buf:指向:要写入的数据,的缓冲区指针
    • count:要写入的字节数
  • 返回
    • 成功:实际写入的字节数
    • 失败:-1,并设置errno
  • 写入类型
    • 对于系统而言,没有什么文本写入和二进制写入(这是语言层的概念)
    • 你传什么指针,他就写什么,如果你原来数据是一个int a,指针传&a,则它就是按二进制写

在这里插入图片描述
readwrite一样,只是这里是读到buf

其余closelseek接口类似C语言

使用示例

以写入为例:

 45 int main()46 {47     int fd = open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666); // 这个打开的效果就相当于 C 语言库函数的直接 mode 为 a48     const char* str = (char*)"hello world!\n";49     write(fd, str, strlen(str)); // 不写入 '\0'50     char fd_str[20];51     sprintf(fd_str, "%d\n", fd);  // 转换为文本52     write(fd, fd_str, strlen(fd_str));53     close(fd);54     return 0;55 } 

通常如果是read,则open就是用带两个参数的

运行结果:
在这里插入图片描述

库函数和系统调用

  • 语言层的文件结构体FILE里面会存储文件描述符fd,用于给下层的系统调用传递
  • C语言的库函数fwritefread其实都是对底层系统调用writeread的封装,在上层为用户提供便利。
  • C语言的库函数具有可移植性,但是系统调用没有
    • 系统调用,如:Linux 的,用的是Linux这一套的。如果把代码移植到Windows或者其他操作系统就不行了
    • C语言,C的fwritefread是对系统调用的封装,但是它不只封装一份操作系统的,它会实现多个操作系统的。后续根据自己在哪个操作系统上使用,通过条件编译(裁剪),来调用对应的系统接口

4 文件描述符(重点)

什么是文件描述符?
如上图所展示的 3 就新打开的log.txt的文件描述符
0, 1, 2分别对应 stdin, stdout, stderr

那系统是如何通过文件描述符来找到要访问的文件的呢?
在这里插入图片描述

  • 在进程的task_struct里面有一个files指针,指向文件描述表files_struct
  • 在文件描述表中,有fd_array[]指针数组,数组的下标对应着文件描述符,指向对应的文件
  • 而每个文件被描述成一个结构体struct file(类似C语言的FILE),里面存储着文件的信息

有了文件描述符fd,进程就会在自己的文件描述表里面找对应下标的文件指针,然后就可以访问对应的文件了。

在这里插入图片描述

文件描述符的分配原则

files_struct数组当中,找到当前没有被使用的最小的⼀个下标,作为新的⽂件描述符。
比如,一开始有0, 1, 2

  • 直接创建一个新文件,则新文件fd == 3
  • close(1),再创建新文件,则fd == 1

注意:这里的关闭不是真关闭,只是“引用计数 - 1”。

  • 因为一个文件可以同时被多个进程访问
  • 同一个文件也可以被同一个进程的多个下标指针同时指向。比如stdoutstderr其实都是向显示器输出

🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

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

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

相关文章

Java 原生实现代码沙箱之Java 程序安全控制(OJ判题系统第2期)——设计思路、实现步骤、代码实现

在看这一期之前&#xff0c;需要先看上一期的文章&#xff1a; Java 原生实现代码沙箱&#xff08;OJ判题系统第1期&#xff09;——设计思路、实现步骤、代码实现-CSDN博客 Java 程序可能出现的异常情况 1、执行超时 占用时间资源&#xff0c;导致程序卡死&#xff0c;不释…

常见的降维算法

作业&#xff1a; 自由作业&#xff1a;探索下什么时候用到降维&#xff1f;降维的主要应用&#xff1f;或者让ai给你出题&#xff0c;群里的同学互相学习下。可以考虑对比下在某些特定数据集上t-sne的可视化和pca可视化的区别。 一、什么时候用到降维&#xff1f; 降维通常…

理解Yocto项目中`${D}`作为模拟目标系统根文件结构的临时目录

在Yocto项目中,理解${D}作为模拟目标系统根文件结构的临时目录,可以通过以下具象化的比喻和结构解析来把握其核心逻辑: 一、沙盒模型:构建系统的“实验场地” ${D}的作用类似于建筑师在施工前搭建的1:1实体模型。它完全模仿目标设备的文件系统布局(如/usr/bin、/etc等目录…

第十课认识约数

课堂学习&#xff1a; 情景引入&#xff1a; 今天我们来认识一下数学中的约数关系&#xff0c;上节课我们了解完倍数之后就已经对约数有了基本的概念&#xff01; 我们按照是否有余数&#xff0c;可以把他们分成两类 在整数除法中&#xff0c;如果商是整数没有余数&#x…

【Vue】vuex的getters mapState mapGetters mapMutations mapActions的使用

目录 一、getters 二、 mapState 三、 mapGetters 四、 mapMutations 五、 mapActions 学到这儿来个小总结&#xff1a;四个map方法的使用 总结不易~ 本章节对我有很大的收获&#xff0c; 希望对你也是&#xff01;&#xff01;&#xff01; 本节素材已上传至Gitee&…

html object标签介绍(用于嵌入外部资源通用标签)(已不推荐使用deprecated,建议使用img、video、audio标签)

文章目录 HTML <object> 标签详解基本语法与核心属性关键属性解析1. **data**2. **type**3. **width & height**4. **name** 嵌入不同类型的资源1. **嵌入图像**2. **嵌入音频**3. **嵌入视频**4. **嵌入 PDF** 参数传递与回退内容**参数&#xff08;<param>&a…

警备,TRO风向预警,In-N-Out Burgers维权风暴来袭

本案是TME律所代理的5月首案&#xff0c;传奇连锁快餐品牌In-N-Out Burgers委托维权&#xff01; 案件基本情况&#xff1a; 起诉时间&#xff1a;2025-5-1 案件号&#xff1a;25-cv-04767 品牌&#xff1a;In-N-Out 原告&#xff1a;In-N-Out Burgers 原告律所&#xff…

数据结构算法习题通关:树遍历 / 哈夫曼 / 拓扑 / 哈希 / Dijkstra 全解析

已知一棵二叉树先序遍历和中序遍历分别为 ABDEGCFH 和 DBGEACHF&#xff0c;请画出这个二叉树的逻辑结构并写出后序遍历的序列。 先序遍历&#xff1a;ABDEGCFH 中序遍历&#xff1a;DBGEACHF 先序遍历看出根为A&#xff0c;左子树DBGE&#xff0c;右子树CHF A的左子树 再…

C++GO语言微服务和服务发现

目录 01 03-go-micro简介 02 04-服务发现的简单认识 03 05-consul的安装 04 06-consul常用的命令 05 07-注册服务到consul并验证 06 08-consul健康检查 07 09-consul结合grpc使用-上&#xff08;只实现grpc远程调用&#xff09; 08 10-consul结合grpc使用-中&#xff08…

HDFS 常用基础命令详解——快速上手分布式文件系统

简介&#xff1a; 本文面向刚接触 Hadoop HDFS&#xff08;Hadoop 分布式文件系统&#xff09;的读者&#xff0c;结合 CSDN 博客风格&#xff0c;系统梳理最常用的 HDFS 客户端命令&#xff0c;并配以示例和注意事项&#xff0c;帮助你在开发和运维中快速掌握 HDFS 的文件管理…

VUE CLI - 使用VUE脚手架创建前端项目工程

前言 前端从这里开始&#xff0c;本文将介绍如何使用VUE脚手架创建前端工程项目 1.预准备&#xff08;编辑器和管理器&#xff09; 编辑器&#xff1a;推荐使用Vscode&#xff0c;WebStorm&#xff0c;或者Hbuilder&#xff08;适合刚开始练手使用&#xff09;&#xff0c;个…

make和makefile的使用,以及写一个简单的进度条程序

1.自动化构建-make/makefile 1.1 背景 一个工程文件中的文件不计其数&#xff0c;其按类型、功能、模块放在若干目录中&#xff0c;makefile定义了一系列规则来指定哪些文件需要先编译&#xff0c;哪些文件需要后编译&#xff0c;哪些文件需要重新编译&#xff0c;甚至于过呢…

数据结构中的栈与队列:原理、实现与应用

前言&#xff1a;栈和队列是计算机科学中两种最基础的线性数据结构&#xff0c;它们的独特操作规则和广泛的应用场景使其成为每一位开发者必须掌握的核心知识。本文将通过生活案例、代码实现和实际应用场景&#xff0c;带您深入理解这两种数据结构的精髓。 1.栈&#xff08;Sta…

如何选择自己喜欢的cms

选择内容管理系统cms what is cms1.whatcms.org2.IsItWP.com4.Wappalyzer5.https://builtwith.com/6.https://w3techs.com/7. https://www.netcraft.com/8.onewebtool.com如何在不使用 CMS 检测器的情况下手动检测 CMS 结论 在开始构建自己的数字足迹之前&#xff0c;大多数人会…

SDC命令详解:使用all_outputs命令进行查询

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html all_outputs命令用于创建一个输出端口对象集合&#xff0c;关于设计对象和集合的更详细介绍&#xff0c;可以参考下面的博客。 Synopsys&#xff1a;设计对象https://chenzhang.blog.csdn…

vue 中的ref

vue 中的ref vue 中的ref 1. ​​ref​​ ** 的基本作用** 在 Vue 中&#xff0c;ref 是用来获取 DOM 元素或者组件实例的一种方式。对于 <el-form> 组件&#xff0c;通过 ref 可以获取到该表单组件的实例&#xff0c;进而调用表单组件提供的各种方法和访问其属性。 …

数据库版本控制工具--flyway

一. 什么是Flyway Flyway 是一款开源的数据库迁移工具。它采用简单直观的方式管理数据库变更&#xff0c;通过版本化的迁移脚本确保数据库结构的一致性和可重复性。无论是开发环境、测试环境还是生产环境&#xff0c;Flyway 都能确保数据库变更按照预期顺序执行&#xff0c;避…

C++使用PoDoFo库处理PDF文件

&#x1f4da; PoDoFo 简介 PoDoFo 是一个用 C 编写的自由开源库&#xff0c;专用于 读取、写入和操作 PDF 文件。它适用于需要程序化处理 PDF 文件的应用程序&#xff0c;比如批量生成、修改、合并、提取元数据、绘图等。 &#x1f31f; 核心特点 特性说明&#x1f4c4; P…

论文分享➲ arXiv2025 | TTRL: Test-Time Reinforcement Learning

TTRL: Test-Time Reinforcement Learning TTRL&#xff1a;测试时强化学习 https://github.com/PRIME-RL/TTRL &#x1f4d6;导读&#xff1a;本篇博客有&#x1f9a5;精读版、&#x1f407;速读版及&#x1f914;思考三部分&#xff1b;精读版是全文的翻译&#xff0c;篇幅较…

dify插件接入fastmcp示例

文章目录 1. 使用python完成mcp服务1.1 准备环境&#xff08;python安装fastmcp&#xff09;1.2 mcp服务端示例代码1.3 启动mcp服务端 2. dify接入2.1 安装MCP SSE和 Agent 策略&#xff08;支持 MCP 工具&#xff09; 插件2.2 dify agent插件配置mcp:2.3 mcp服务配置&#xff…