【linux】文件操作(IO)详述

news2024/9/23 3:23:14

文件操作

  • 一、引入
  • 二、系统调用接口
    • 2.1 open与close
    • 2.2 write
    • 2.3 read
  • 三、文件描述符
    • 3.1 分配规则
  • 四、重定向
    • 4.1 输出重定向
    • 4.2 追加重定向
      • 4.3 输入重定向
      • 4.4 独立性
  • 五、缓冲区
    • 5.1 缓冲区刷新策略
    • 5.2 缓冲区位置
    • 5.3 现象解释
  • 六、文件系统
    • 6.1 文件系统分区
      • 6.1.1 分区图
      • 6.1.2 介绍
      • 6.1.3 软硬链接
        • 6.1.3.1 链接方法
        • 6.1.3.2 软硬链接区别
  • 七、动态库和静态库
    • 7.1 概念
    • 7.2 静态库与静态链接
    • 7.3 动态库与动态链接
    • 7.4 fPIC

一、引入

我们知道每个语言都有自己的文件操作接口且各不相同,而OS访问磁盘中的文件必须要有一个系统调用接口 。所以上层语言不管如何变化,底层接口不会变。所以我们只需要学习底层接口就可以了。

二、系统调用接口

2.1 open与close

open
在这里插入图片描述

返回值:
在这里插入图片描述
close
在这里插入图片描述

参数:

O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
O_TRUNC: 覆盖写
注:这些都是宏,使用每个比特位作为标志位。

现在我们来创建一个文件:
使用O_WRONLY

在这里插入图片描述
运行后没有出现log.txt文件,那我们加上第二个宏选项:O_CREAT
在这里插入图片描述
运行后:
在这里插入图片描述
可以看到权限上都是乱码。所以我们知道需要自己来添加默认权限。

在这里插入图片描述
在这里插入图片描述

2.2 write

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.3 read

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、文件描述符

3.1 分配规则

一个进程可以打开多个文件,所以OS需要把这些文件管理起来,而管理的方式就是使用文件描述符。
在这里插入图片描述
在这里插入图片描述
我们可以看到fd是从3开始,那么0,1,2呢?
默认打开的三个标准输入输出流:

三个标准输入输出流
stdin 标准输入(键盘)
stdout 标准输出(显示器)
stderr 标准错误输出(显示器)

引入一个概念:系统调用接口访问文件必须要用文件描述符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,如果不加close(0),fd默认是3,而关掉0时,fd就变成了0。
所以我们就可以知道fd的分配规则

从小到大寻找没有被占用的位置。

四、重定向

4.1 输出重定向

在这里插入图片描述
这个进程的意思就是把标准输出流关闭,使1(fd)的位置指向log.txt,所以他会把数据输出到log.txt中
但是我们在log.txt并没有发现出现任何内容。这就是缓冲区刷新原则
在这里插入图片描述
在这里插入图片描述
而这种本来应该往显示屏上打印却打印到文件中的操作我们称之为重定向

系统给了我们一个重定向的接口:
dup2
在这里插入图片描述
int dup2(int oldfd,int newfd);
它的意思就是把oldfd的内容拷贝到newfd的位置,oldfd和newfd都指向同一个文件。

在这里插入图片描述
在这里插入图片描述

4.2 追加重定向

追加重定向其实跟dup2没有关系,而是在open处做修改:
在这里插入图片描述
在这里插入图片描述

4.3 输入重定向

在这里插入图片描述
在这里插入图片描述
这里就是把本来应该从键盘输入内容的重定向到文件中。

4.4 独立性

当我们用子进程进行程序替换的时候,会不会影响到父进程呢?

答案是不会,进程具有独立性。子进程的PCB会指向一个新创建的files_struct。

在这里插入图片描述
这里补充一点:

当我们重定向好一个文件后,如果发生了程序替换,并不会影响重定向的文件!

五、缓冲区

先来看一个现象:
在这里插入图片描述
正常输出:
在这里插入图片描述
重定向到文件中:
在这里插入图片描述
我们发现C语言接口输出了两次

这里就跟缓冲区有关系了。

首先要知道缓冲区就是一块内存

缓冲区的意义:

当我们想IO时,直接把数据拷贝到缓冲区,拷贝函数就可以返回了,接着运行后续程序。所以它可以节省进程数据进行IO的时间。

就像fwrite函数,我们可以把它理解为拷贝函数,它会将进程中的数据拷贝到缓冲区或者外设。

5.1 缓冲区刷新策略

现在我们有一块数据想要刷新到外设,是一次写入到外设还是多次写入外设效率高呢?

答案是一次写入效率最高,因为访问外设次数少。

所以缓冲区会结合具体的设备,定制刷新策略。
1️⃣ 立即刷新(无缓冲)
2️⃣ 行刷新(行缓冲 ——> 显示器)
3️⃣ 缓冲区满则刷新(全缓冲 ——> 磁盘文件)
当然会有特殊情况
① 用户强制刷新(fflush)
② 进程退出(退出时一般会刷新缓冲区)

5.2 缓冲区位置

我们首先可以知道缓冲区一定不在内核中,因为如果在内核中,write也应该打印两次!!
我们之前讲的所有的缓冲区都指的是用户级语言层面提供的缓冲区这个缓冲区在FILE结构体中

FILE结构体:
在这里插入图片描述

5.3 现象解释

现在我们就可以对上述情况进行解释:

当我们没有重定向的时候,stdout默认对应的是行刷新,在fork之前C函数已经将数据打印到外设中了,此时FILE中就没有数据了
当我们重定向时,写入的文件就不是显示器了,是普通文件,而普通文件对应的刷新策略是全缓冲,数据不足以写满缓冲区,此时执行fork后。创建子进程后,子进程退出时,数据会直接刷新。而刷新会引起写实拷贝!!,而父进程最后也会刷新一次,所以C语言接口会刷新两次。
而为什么write系统接口没有刷新两次呢?上述的过程都跟write无关。因为write没有FILE,用的是fd,没有C提供的缓冲区

六、文件系统

我们知道磁盘的空间很大,所以要进行分区管理

6.1 文件系统分区

6.1.1 分区图

在这里插入图片描述

6.1.2 介绍

文件需要存属性+内容

inode用来存储文件的属性,是固定大小的。每一个文件都有自己的inode,为了区分每个inode,他们都会有自己的id:

在这里插入图片描述

Date Block存储的是文件的内容

上面两个都有一个BitMap是用来记录存储情况的。
而GDT则是对应的宏观存储状态。

6.1.3 软硬链接

6.1.3.1 链接方法

软链接:
在这里插入图片描述

硬链接:
在这里插入图片描述

6.1.3.2 软硬链接区别

软硬链接的区别就是是否具有独立的inode

软链接具有独立的inode,可以当作独立文件
硬链接没有独立的inode

那么我们怎么理解硬链接呢?
当我们往文件写入数据后
在这里插入图片描述
可以看出写入数据后硬链接的大小会变化而软链接不会变。
得出结论:创建硬链接没有创建新文件。 它就是在指定路径下新增文件名和inode的映射关系。

一个inode可能被多个硬链接指向,所以inode有一个计数器,记录有多少个指向它,叫做硬链接数。
在这里插入图片描述
当我们删除log.txt时:
在这里插入图片描述
可以看到hard_file.link的硬链接数变成1。
我们可以得出结论:
当一个文件的硬链接数为0的时候,这个文件才算真正被删除。
在这里插入图片描述
软链接无法读取原来log.txt的内容,说明软链接不是用inode找文件,而是用的文件名(目标文件的路径)。

不同目录下的软链接:
在这里插入图片描述
硬链接数细节问题:
在这里插入图片描述

创建一个目录硬链接数直接变成了2,原因是dir目录里面有.

在这里插入图片描述
在这里插入图片描述
所以...就是给目录建立的硬链接,这里要注意的是:
普通用户不能给目录建立硬链接。

七、动态库和静态库

7.1 概念

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

在这里插入图片描述
现在我们写了加法和减法的进程
1️⃣ 先把.cc文件变成.o文件
在这里插入图片描述
现在我们在另一个目录下创建main.c文件,为了使用我们可以把.o文件传过去。
但是光有.o文件不够,还需要.h文件

当我们不想让别人看看到源代码的时候就可以这么传递。
所以就出现了库的思想:

我们可以把所有的”.o“文件打一个包,形成一个库文件。而打包方式的不同又可以分为静态库和动态库。

7.2 静态库与静态链接

生成静态库

在这里插入图片描述
但是我们想要把库给别人使用,还得把.h文件也传过去。
在这里插入图片描述
在这里插入图片描述
接下来就可以发送库文件了。
发送完后需要进行安装

安装的意思其实就是把库拷贝到指定系统的路径下

在这里插入图片描述
但是此时我们编译不会成功,因为找不到.h文件和库文件
所以我们需要指明头文件路径-I,指明库文件路径-L。这里要注意如果我们要链接库就需要指明库名称。 而这个名称要去掉前缀和后缀
在这里插入图片描述

gcc/g++默认都是动态链接,但如果只有动/静态库,那么就只会会动/静态链接,如果动静态库都有则会动态链接。

当然我们也可以把库文件拷贝到/lib64/,把头文件拷贝到/usr/include/这样编译的时候只用加库名称就可以了。

7.3 动态库与动态链接

要形成动态库还是一样要把源文件便变成.o文件,与静态库不同的是要加-fPIC选项
打包的时候要用g++使用-shared选项。
在这里插入图片描述
然后我们就可以创建一个目录把头文件和库包放进去再传给别人。
而链接的过程跟静态链接一样。
在这里插入图片描述
但是运行的时候会报错。因为动态链接和静态链接不一样,它在运行的时候操作系统需要找到库,但此时库不在系统路径下,操作系统无法找到。

那么怎么告诉操作系统库在哪里呢?
1️⃣ 环境变量

在这里插入图片描述
我们可以把路径添加到环境变量中。
在这里插入图片描述

2️⃣ 配置文件

在这里插入图片描述
我们把库文件路径写在任意一个配置文件中即可,为了方便删除我们可以创建一个新文件。
在这里插入图片描述
这里要注意使用ldconfig更新动态库缓存。

3️⃣ 软链接

在这里插入图片描述
当然我们也可以软链接到系统指定的目录下(/lib64)。

7.4 fPIC

静态库会把代码拷贝到代码区,而这部分代码会使用绝对地址来查找。
而动态库则用的是fPIC:
fPIC就是产生位置无关码,就是相对位置。他会把动态库指定函数的地址写到可执行程序中。
在程序运行的时候会把动态库加载到共享区(在堆和栈之间)

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

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

相关文章

实时推荐业务介绍 grpc接口对接

5.1 实时推荐业务介绍 学习目标 目标 无应用 无 5.1.1 实时推荐逻辑 逻辑流程 1、后端发送推荐请求,实时推荐系统拿到请求参数 grpc对接2、根据用户进行ABTest分流 ABTest实验中心,用于进行分流任务,方便测试调整不同的模型上线3、推荐中心…

k8s之部署有状态应用

写在前面 本文一起看下k8s对于有状态应用部署提供的解决方案。 1:有状态应用和无状态应用 如果是一个应用每次重启时依赖环境都能和第一次启动时的完全一致,则就可以称这类应用是无状态应用用,反之,就是有状态应用,如…

自动写代码的AI工具,已经支持 VsCode 插件安装使用

自动写代码的AI工具,已经支持 VsCode 插件安装使用,它的功能并不是「代码补全」,而是「代码生成」。 之前有个比较火的 GitHub Copilot,但是这是商业产品,并且没有开源,现在又被告了。 GitHub Copilot 面…

SQLSERVER 事务日志的 LSN 到底是什么?

一:背景 1. 讲故事 大家都知道数据库应用程序 它天生需要围绕着数据文件打转,诸如包含数据的 .mdf,事务日志的 .ldf,很多时候深入了解这两类文件的合成原理,差不多对数据库就能理解一半了,关于 .mdf 的合…

代码随想录--二叉树章节总结 Part II

代码随想录–二叉树章节总结 Part II 1.Leetcode222 求完全二叉树结点的个数 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达…

Python机器学习:特征变换

🌕 特征变换 特征变换主要就是针对一个特征,使用合适的方法,对数据的分布、尺度等进行变换,以满足建模时对数据的需求。 特征变换可分为数据的数据的无量纲化处理和数据特征变换。 🌗 数据的无量纲化处理 常用处理…

22.0:Codejock Suite Pro for ActiveX COM:Crack

从 Visual Basic 5.0 和 6.0 开始一直到当前版本的 Visual Studio 的大多数 ActiveX 容器。与 Visual Studio 无缝集成并包含我们所有 ActiveX COM 产品的评估版本。评估版不提供 OCX 文件的 Unicode 版本。 创建包含一整套高度可定制的用户界面组件的专业应用程序,…

Flink-FinkSQL基本操作(Table API、动态表、事件窗口、分组聚合开窗查询、联结查询)

11 Table API和SQL 11.1 快速上手 引入TableAPI的依赖 桥接器 <dependency><groupId>org.apache.flink</groupId> <artifactId>flink-table-api-java-bridge_${scala.binary.version}</artifactId><version>${flink.version}</vers…

12、常用插件

文章目录12、常用插件推荐1&#xff1a;Alibaba Java Coding Guidelines推荐2&#xff1a;jclasslib bytecode viewer推荐3&#xff1a;Translation推荐4&#xff1a;GenerateAllSetter推荐5&#xff1a;Rainbow Brackets推荐6&#xff1a;CodeGlance Pro推荐7&#xff1a;Stat…

7.bWAPP -- INSECURE DIRECT OBJECT REFERENCES

7.bWAPP – INSECURE DIRECT OBJECT REFERENCES 0x01、Insecure DOR (Change Secret) 同 XSS - Stored (Change Secret) Low 仔细观察页面, 发现隐藏一个input标签, 作用是输入用户名, 并且配合提交的修改密码, 完成修改用户密码的操作: 这里就可以利用该用户名input标签达…

如何带好一个团队?团队管理的要点有哪些?

想带好一个团队并不是这么容易&#xff0c;尤其是对于新晋升管理者来说更是难上加难。团队管理可以大大提高工作效率。那么&#xff0c;团队管理的要点是什么呢&#xff1f; 1、远景和目标 成员们先要有一个共同的目标&#xff0c;在此基础上还必须要有一个好的愿景&#xff0…

即时通讯系列---如何下手做技术方案设计

1. 引出主题 IM整体涉及的内容比较多, 做技术方案设计需要慎重, 可以先从功能列表以及核心case逐步的总结出技术方案 本文结构: 1. 查看功能列表 2. 核心case分析 3. 总结技术方案设计 2. 如何做技术方案设计 1. 查看功能列表 功能清单 一级分类 二级分类 三级分类…

TCP/UDP网络编程

目录 一、常见的客户端服务端模型 二、Socket套接字 1、概念 2、分类 a、流套接字 b、数据报套接字 c、原始套接字 三、UDP数据报套接字编程 四、TCP数据报套接字编程 一、常见的客户端服务端模型 客户端&#xff1a;用户使用的程序。 服务端&#xff1a;给用户提…

miracl编译及使用

文章目录Windows平台编译网址 https://miracl.com/https://github.com/miracl/MIRACL Windows平台编译 源码目录下新建文件夹ms32或ms64&#xff0c;把/lib/ms32doit.bat或ms64doit.bat分别拷进去。 把源码include和source目录所有文件拷贝进要编译的ms32或ms64&#xff0c…

【高阶数据结构】海量数据如何处理? (位图 布隆过滤器)

&#x1f308;欢迎来到高阶数据结构专栏~~位图 & 布隆过滤器 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff0…

模拟实现list / list迭代器

前言&#xff1a;学习C的STL&#xff0c;我们不仅仅要求自己能够熟练地使用各种接口&#xff0c;我们还必须要求自己了解一下其底层的实现方法&#xff0c;这样可以帮助我们写出比较高效的代码程序&#xff01; ⭐在本篇文章中&#xff0c;list的迭代器是重点&#xff0c;它不…

WSL2配置网络代理

注意&#xff1a;本文参考自文章&#xff1a;WSL2配置代理&#xff0c;是对原文的补充&#xff0c;使其适用于河对岸云服务代理。 1 开启Windows代理 1.1 开启代理软件的局域网访问权限 请注意&#xff1a;本文的WSL2代理配置&#xff0c;需要Windows的代理软件已经能够正常…

HTTPS详解及HTTPS实验

目录 HTTPS 一&#xff0c;https在参考模型中的位置 二&#xff0c;什么是HTTPS 三&#xff0c;什么是SSL 1&#xff0c;SSL 协议分为两层&#xff1a; 2&#xff0c;SSL 协议提供的服务&#xff1a; 四&#xff0c;HTTPS的加密方式 1&#xff0c;常见的加密算法 2&#xff0c;…

mysql知识点

目录 1.mysql聚合函数&#xff1a; 2.having&#xff08;用来过滤数据&#xff09;&#xff1a; HAVING 不能单独使用&#xff0c;必须要跟 GROUP BY 一起使用 WHERE 与 HAVING 的对比 3.升序和降序 4.等于 5.实战demo&#xff1a; 1.mysql聚合函数&#xff1a; 常用的聚…

codeforces签到题之div3

前言 第一次&#xff43;&#xff4f;&#xff44;&#xff45;&#xff46;&#xff4f;&#xff52;&#xff43;&#xff45;&#xff53;&#xff0c;发现几个问题&#xff1a; 1,不知道选&#xff4c;&#xff41;&#xff4e;&#xff47;&#xff55;&#xff41;&…