Linux之基础IO(下)

目录

缓冲区的概念

深入理解文件系统

创建文件的整个过程

软链接

硬链接


上一节课我们学习了基础IO中的文件的读写操作,以及文件描述符的概念和重定向的基本原理,本期我们继续进行基础IO的学习。

缓冲区的概念

在讲缓冲区之前,大家先看看下述代码。

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>int main()
{close(1);int fd=open("./log.txt",O_CREAT|O_WRONLY,0644);const char* msg="hello yjd\n";//通过write接口往1号文件描述符所指向的文件中写入数据write(1,msg,strlen(msg));//通过printf函数和fprintf函数往1号文件描述符所对应的文件中写入数据printf("%s",msg);fprintf(stdout,"%s",msg);return 0;
}

这段代码其实就是我们完成了一个输出重定向,将向显示器文件写的数据全部写到了文件中。

运行结果如下。

通过运行结果发现,我们确实将对应的字符串数据写入了log.txt这个文件中。

如果我们往代码中加入这一行代码会发生什么现象呢?

 

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>int main()
{close(1);int fd=open("./log.txt",O_CREAT|O_WRONLY,0644);const char* msg="hello yjd\n";//通过write接口往1号文件描述符所指向的文件中写入数据write(1,msg,strlen(msg));//通过printf函数和fprintf函数往1号文件描述符所对应的文件中写入数据printf("%s",msg);fprintf(stdout,"%s",msg);close(1);return 0;
}

我们往代码中加入了close(1)这行代码,我们再来看看运行结果。

运行结果如下。

 我么发现,为什么重定向的时候,只往log.txt中写入了一个字符串文件呢?按道理说应该是三个呀。这究竟是为什么?这就要学习我们今天的缓冲区的知识。我们以往用到printf函数和scanf这些函数,以及用到cin,cout这些流操作,我们通常认为要么是从键盘上获取数据,要么是往显示器打印数据。难道这些数据是直接写到相关硬件所对应的文件上去的吗?

之前我们讲到了一点,这些函数和流操作都是处于用户层的,用户层是无法向底层的硬件文件中写入数据的,用户层要往底层硬件写入数据,必须贯穿操作系统,那么这些流操作和函数是怎样把数据写入底层的文件的呢?用一个示意图为大家直观讲解。

示意图如下。

 

 我们使用的printf和fprintf函数都是往stdout标准输出流中进行数据写入。stdout的类型是FILE*类型,FILE*指向了一个结构体类型,这个结构体里封装了文件描述符和一个c语言缓冲区。所以我们可以形象的理解为stdout等等这些流都是一个用户缓冲区。我们首先将数据写入c语言缓冲区,然后再将c语言缓冲区中的数据刷新到文件内核缓冲区,然后再把文件缓冲区中的数据刷新到硬件设备文件中。

那么从c语言缓冲区刷新到文件内核缓冲区中的刷新策略是什么呢?

主要分为三种:

1.立即刷新(不缓冲)。

2.行刷新(行缓冲)。向显示器文件的内核缓冲区,就是行缓冲。

3.当缓冲区满了再进行刷新(全缓冲)。向普通文件的内核缓冲区,就是全缓冲。

一般情况下,全缓冲时,如果缓冲区没满,但是进程推出了,也会将缓冲区进行刷新。

 有了这些知识,对于刚开始的情景我们便可以进行解释。

重定向时,因为是往log.txt中进行数据的写入,log.txt是一个普通文件,所以它的刷新策略就是全缓冲,但是我们进行文件写入的时候,缓冲区没有写满,所以没有刷新,但是当我们进程退出时,c语言缓冲区的文件就刷新到了文件的内核缓冲区,最终写入了磁盘设备的log.txt文件中。

可是文件内核缓冲区怎么知道要往哪个文件进行刷新呢?

因为std是一个FILE*类型,其指向的结构体中存储了文件描述符,这个文件描述符,就是将来文件内核缓冲区要刷新的硬件文件目标。所以上述第二个代码我们关闭文件描述符之后,在进程退出时,c语言缓冲区中的数据并不会刷新到文件内核缓冲区,因为关闭了fd就不知道要往哪个文件里刷新,所以干脆不往文件内核缓冲区中进行刷新。但是write函数接口是一个系统调用接口,是直接往文件内核缓冲区中进行数据的写入的,文件内核缓冲区中的数据是会立即写入对应的文件的,所以,write函数的写入是不受close(fd)的影响的。

要close(fd)之后,继续刷新缓冲区中的文件,就要在close(fd)之前,加上fflush(stdout)的代码。

以上便就是文件缓冲区的概念。         

深入理解文件系统

在一个文件被打开时,我们为之创建了struct file类型的数据结构进行管理,当一个文件没有打开时,这个文件存储在哪里呢?这个文件是存储在磁盘上的。磁盘是什么呢?

要说磁盘是什么,我们得先了解一下硬盘。硬盘分为机械硬盘和固态硬盘。

机械硬盘的特点:便宜,使用周期长。重,速度慢。

固态硬盘的特点:速度快,便捷。贵,使用周期短。

 我们基于机械硬盘来了解文件系统。

上述结构中我们只需要关心盘片即可。盘片被分成了多个同心环,每一个换又被分成了多个扇区。一个扇区的大小为512Byte。

我们最终将整个盘面分为了一个有多个扇区组成的线性存储结构。一个磁盘的空间是很大的,为了方便进行管理,我们将磁盘进行了分区,比如我们电脑上常见的C,D,E,F盘。但是每个分区依旧是很大的,所以为了方便管理,我们又把每个分区分成了多个block块。

其中BOOT BLOCK中存放的就是系统启动的相关数据。Block group中存储相关的数据。但是此时每一个Block group依然很大,所以我们又要对每个Block group进行划分。

基于上图。

 Super Block:用于统计每个分区的所有的Block group的相关信息,比如使用了多少Inode,使用了多少Block等等。

Group Descriptor Table:用于统计当前组的相关信息,使用了多少了Inode,使用了多少Block块。

Block Bitmap:位图结构,用于统计数据块(Blocks)的使用情况,当前位为0为未被使用,为1为已经使用。

Inode Bitmap:位图结构,用于统计Inode块的使用情况。

Inode Table:里面为多个Inode块,inode块为一个结构体,每一个inode块都存储文件的相关属性数据。可以通过block数组定位数据块中所使用的数据块。

Data Blocks:里面有多个block块,用于存储文件的内容数据。 

看到上图大家可能会有疑惑,这个inode是什么呢?

作为用户,我们使用文件名辨别一个文件,但是操作系统并不是通过文件名来辨别文件,是通过一个叫inode的编号来辨别文件。可以这样理解,一个文件只有一个inode但是可以有多个文件名,所以操作系统用inode编号来辨别文件。

目录是文件吗?

通过上图我们可以看到,目录有它的属性,有它的inode编号,那么目录的Data Blocks里面存放什么数据呢?

目录的Data Blocks中存储的是文件的inode编号。当我们们创建一个文件时,操作系统会一起创建一个inode编号,这个inode编号被其当前目录所存储。

创建文件的流程

上述指令,操作系统底层是怎样执行的呢?

当创建一个文件时,操作系统同时会为这个文件分配一个inode编号,然后通过inode bitmap去查看没有被使用的inode块,找到之后,将当前文件的inode编号填入对应的inode块中,并且填入文件的先关属性数据,将当前inode块的位图置为1。

当对文件写入数据时,先在block bitmap中查找没有使用的数据块,找到之后,对这些数据块进行数据的写入,最终将这些数据块下标存储在inode块中的的block数组中。方便后续进行查找。

当查找一个文件时,先通过文件的inode编号查找到对应的inode块,然后通过里面的block数组找到对应的数据块,然后访问数据块中的数据。

软链接

创建软链接:ln -s 源文件名  链接名

我们发现运行软链接,也可以运行我们对应的可执行程序,所以这个软链接其实本质上就是一个快捷方式,与windows中的快捷方式相同。当我们的一个文件存储的位置比较深时,可以使用软链接的方式快速进行访问。

软连接的删除方式:unlink 连接名称

硬链接

硬链接的创建方式:ln 源文件名 链接名

我们发现,创建的硬链接也可以直接进行运行,难道它也是我们源文件的一个快捷方式吗?这不由得就产生了软链接和硬链接的区别。通过ll -i指令查看这两个链接的详细信息。

 我们发现软链接的inode编号与源文件不相同,但是硬链接的inode编号与源文件竟然出奇的相同,所以这便可以告诉我们答案,软链接是一个单独的文件,有自己的inode编号,软链接的data blocks里面存储的就是源文件的路径。硬链接不是一个单独的文件与源文件共享inode,是源文件的一个重命名。

 不知道大家之前有没有注意到属性那几列中的用彩色方框标记的这一列整数是什么含义呢?我们不妨再创建几个硬链接,然后再删除一个硬链接。

[yjd@hecs-87060 test7]$ ll
total 36
-rw-rw-r-- 1 yjd yjd    0 Jul 26 17:38 hello.c
-rw-r--r-- 1 yjd yjd   30 Jul 26 17:51 log.txt
-rw-rw-r-- 1 yjd yjd   58 Jul 26 11:36 makefile
-rwxrwxr-x 2 yjd yjd 8360 Jul 26 17:55 test
-rw-rw-r-- 1 yjd yjd  641 Jul 26 17:55 test.c
lrwxrwxrwx 1 yjd yjd    4 Jul 26 17:57 test_link -> test
-rwxrwxr-x 2 yjd yjd 8360 Jul 26 17:55 test_link_hard
[yjd@hecs-87060 test7]$ ln test  test_link_hard1
[yjd@hecs-87060 test7]$ ln test  test_link_hard2
[yjd@hecs-87060 test7]$ ll
total 60
-rw-rw-r-- 1 yjd yjd    0 Jul 26 17:38 hello.c
-rw-r--r-- 1 yjd yjd   30 Jul 26 17:51 log.txt
-rw-rw-r-- 1 yjd yjd   58 Jul 26 11:36 makefile
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test
-rw-rw-r-- 1 yjd yjd  641 Jul 26 17:55 test.c
lrwxrwxrwx 1 yjd yjd    4 Jul 26 17:57 test_link -> test
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test_link_hard
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test_link_hard1
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test_link_hard2
[yjd@hecs-87060 test7]$ ln test  test_link_hard3
[yjd@hecs-87060 test7]$ ll
total 72
-rw-rw-r-- 1 yjd yjd    0 Jul 26 17:38 hello.c
-rw-r--r-- 1 yjd yjd   30 Jul 26 17:51 log.txt
-rw-rw-r-- 1 yjd yjd   58 Jul 26 11:36 makefile
-rwxrwxr-x 5 yjd yjd 8360 Jul 26 17:55 test
-rw-rw-r-- 1 yjd yjd  641 Jul 26 17:55 test.c
lrwxrwxrwx 1 yjd yjd    4 Jul 26 17:57 test_link -> test
-rwxrwxr-x 5 yjd yjd 8360 Jul 26 17:55 test_link_hard
-rwxrwxr-x 5 yjd yjd 8360 Jul 26 17:55 test_link_hard1
-rwxrwxr-x 5 yjd yjd 8360 Jul 26 17:55 test_link_hard2
-rwxrwxr-x 5 yjd yjd 8360 Jul 26 17:55 test_link_hard3
[yjd@hecs-87060 test7]$ unlink  test_link_hard3
[yjd@hecs-87060 test7]$ ll
total 60
-rw-rw-r-- 1 yjd yjd    0 Jul 26 17:38 hello.c
-rw-r--r-- 1 yjd yjd   30 Jul 26 17:51 log.txt
-rw-rw-r-- 1 yjd yjd   58 Jul 26 11:36 makefile
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test
-rw-rw-r-- 1 yjd yjd  641 Jul 26 17:55 test.c
lrwxrwxrwx 1 yjd yjd    4 Jul 26 17:57 test_link -> test
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test_link_hard
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test_link_hard1
-rwxrwxr-x 4 yjd yjd 8360 Jul 26 17:55 test_link_hard2

通过上述代码不难发现,当我们在增加删除硬链接时,这一列的数组也会随之发生变化,其实这一列就表示当前文件的硬链接个数。当这个数子变成0时,就意味着当前文件没有了硬链接,也就意味着当前文件即将删除,所以就要把当前文件的inode块的位图置零。这其实就是刚开始我们在inode的那个结构体中设置的成员变量ref,也就是引用计数,当ref为零时,就意味着要删除当前文件,然后就要将当前inode块的位图置零。这也是在Linux中为什么删除一个文件比较快的原因。

好了以上便是linux中文件系统的所有内容。

本期内容到此结束^_^

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

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

相关文章

Java 集合框架:HashMap 的介绍、使用、原理与源码解析

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 020 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

Redis (常用数据结构和命令)

目录 简介 概述 特点 数据结构 常用命令 通用命令 keys del exists expire 与 ttl String 命令 SET 和GET: MSET和MGET INCR和INCRBY和DECY SETNX SETEX Redis 命令 Key 的层级结构 key层级关系 &#xff1a; Hash命令 HSET和HGET HMSET和HMGET HGETALL H…

TypeScript核心

常用操作方式 1、类型推断 ts会根据变量存放的初始值来进行变量类型限定。 如上&#xff1a;开始str是字符串&#xff0c;则此变量以后就只能存字符串值。 开发中的意义&#xff1a;变量分配字符串值&#xff0c;后期可能会书写一些字符串功能、方法等相关的操作&#xff0c;如…

【算法/学习】前缀和差分

前缀和&&差分目录 1. 前缀和的概念及作用 &#x1f308;概念 &#x1f308;用途 &#x1f319;一维前缀和 &#x1f319;二维前缀和 2. 差分的概念及用途 &#x1f308;概念&#xff1a; &#x1f308;用途 &#x1f319;一维差分 &#x1f319;二维差分 1. …

JVM面试题之内存区域、类加载篇

文章目录 引言JVM是什么&#xff1f;1. JVM内存划分2. 对象如何在JVM中创建2.1 内存分配2.2 创建对象步骤 3. JVM类加载流程3.1 双亲委派 总结 引言 Java开发人员在面试中基本都会被问到关于JVM的问题。想要成为高级的开发人员&#xff0c;了解和学习Java运行的原理和JVM是必不…

数据结构——二叉树性质

性质1:在二叉树的第i层上至多有2^(i-1)个结点(i>1)。 这个性质很好记忆&#xff0c;观察一下图6-5-5。 第一层是根结点&#xff0c;只有一个&#xff0c;所以2^(1-1)2^01。 第二层有两个&#xff0c;2^(2-1)22。 第三层有四个&#xff0c;2^(3-1)2^24。 第四层有八个&am…

【年报文本分析】Python+Selium获取互动易平台投资者提问与上市公司回应文本数据

目录 序言excel文件准备全部代码 序言 互动易平台链接&#xff1a;https://irm.cninfo.com.cn/views/interactiveAnswer 需要提前下载好三个库&#xff0c;都可以用pip install轻松下载&#xff0c;稍微麻烦点儿的是需要去下载个对应版本的chromedriver.exe驱动&#xff0c;放…

路由表与IP数据报的转发

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、相关知识 1、路由类型 路由表中有3类路由&#xff1a;直连路由、静态路由、动态路由 直连路由&#xff1a;一般指去往路由器接口直接连接网络的…

mysql中You can’t specify target table for update in FROM clause错误

mysql中You can’t specify target table for update in FROM clause错误 You cannot update a table and select directly from the same table in a subquery. mysql官网中有这句话&#xff0c;我们不能在一个语句中先在子查询中从某张表查出一些值&#xff0c;再update这张表…

【ffmpeg命令入门】视频剪切,倍速与倒放

文章目录 前言1. 视频剪切2. 视频倍速公式说明例子 3. 视频倒放总结 前言 在视频编辑中&#xff0c;剪切、倍速和倒放是常见的操作&#xff0c;能够帮助我们调整视频的长度、播放速度以及播放顺序。掌握 FFmpeg 命令中的相关参数和用法将使视频处理变得更加高效。在这篇文章中…

pytest使用

主要技术内容 1.pytest设计 接口测试 框架设想 common—公共的东西封装 1.request请求 2.Session 3.断言 4.Log 5.全局变量 6.shell命令 ❖ config---配置文件及读取 ❖ Log— ❖ payload—请求参数—*.yaml及读取 ❖ testcases—conftest.py; testcase1.py…….可…

2024年【熔化焊接与热切割】考试题及熔化焊接与热切割考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 熔化焊接与热切割考试题是安全生产模拟考试一点通生成的&#xff0c;熔化焊接与热切割证模拟考试题库是根据熔化焊接与热切割最新版教材汇编出熔化焊接与热切割仿真模拟考试。2024年【熔化焊接与热切割】考试题及熔化…

vue-plugin-hiprint 打印 预览打印+静默打印

1.安装 npm install vue-plugin-hiprint npm i socket.io-client --save //为了静默打印 &#xff08;为此还需安装客户端&#xff09; 2…html页面 引入css <link rel"stylesheet" type"text/css" media"print" href"https://cdn.jsde…

创新大赛中财务预测的策略与技巧

创新大赛中财务预测的策略与技巧 前言财务预测的重要性财务预测的步骤财务预测的关键要素注意事项结语 前言 在当今快节奏、竞争激烈的商业环境中&#xff0c;创新不仅是推动企业成长的动力&#xff0c;更是衡量一个项目能否在市场中脱颖而出的关键。创新大赛作为展示这些创新成…

星耀巴黎,竞猜有礼!为运动健儿加油,让世界看见中国力量

即将高燃来袭首金荣耀&#xff0c;让我们拭目以待&#xff01; 当象征着“更快、更高、更强”的号角再次吹响&#xff0c;谁又能在这场全球瞩目的体育盛宴中&#xff0c;率先触碰那份至高无上的荣耀&#xff1f;“首金”不仅是一个国家或地区体育实力的象征&#xff0c;更是运…

1台solidworks图形工作站同时给5人一起使用

在日益发展的科技环境中&#xff0c;团队协作已成为各个行业不可或缺的一一部分。对于工程设计和图形处理领域而言&#xff0c;SolidWorks等强 大的三维建模和仿真软件成为了日常工作的重要工具。 随着团队规模的扩大和项目复杂性的增加&#xff0c;如何高效、稳定地为多人提供…

Java入门:05.Java中的数组002

通过上篇文章&#xff0c;相信大家对数组应该有了一个简单的了解&#xff0c;并对Java中的数据类型有了一个基本的认识&#xff0c;不仅如此我们还明白了怎样定义一个数组类型的变量&#xff0c;在这之后&#xff0c;让我们一起来更加深入的了解一下数组吧。 三、如何创建一个…

Axure软件新功能解析与应用技巧分享

Axure是一种用于创建原型和交互设计的软件工具&#xff0c;广泛应用于操作界面。&#xff08;UI&#xff09;和客户体验&#xff08;UX&#xff09;为了展示和测试应用程序、网站或其他数据产品的性能和操作界面&#xff0c;设计帮助产品经理、设计师和开发者制作具有交互性的原…

Ghost Buster Pro for Mac:系统优化的得力助手

Ghost Buster Pro for Mac是一款功能强大的系统优化工具&#xff0c;专为Mac用户设计&#xff0c;旨在提供全方位的系统清理、优化和维护服务。 这款软件拥有出色的垃圾清理能力&#xff0c;能够深度扫描并清除Mac上的无效目录、文件、系统日志、下载历史记录、缓存和临时文件…

每日任务:TCP/IP模型和OSI模型的区别

介绍一下TCP/IP模型和OSI模型的区别&#xff1f; OSI模型由国标准化组织提出&#xff0c;而TCP/IP模型是由美国国防部开发的&#xff1b; OSI模型由七个层次组成&#xff0c;从下到上依次为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而TCP/IP模型只有四层…