Linux 基础IO [缓冲区文件系统]

 💓博主CSDN主页:麻辣韭菜-CSDN博客💓

⏩专栏分类:http://t.csdnimg.cn/G90eI⏪

🚚代码仓库:Linux: Linux日常代码练习🚚

🌹关注我🫵带你学习更多Linux知识
  🔝

目录

前言

一.Linux下一切皆文件 

二.缓冲区

1.缓冲区概念

2.缓冲区意义 

3.缓冲区在哪里 

 三.文件系统

1.初识文件系统

2. 扇区中的块组是如何工作的?

3. 理解软硬链接 

 三.动静态库

生成静态库

生成动态库

​编辑 1.导入环境变量方法

 2.修改配置文件

 3.软连接到系统库下面


前言

基础IO讲了什么是fd,以及fd的本质是什么,系统调用接口。本篇重点缓冲区,理解文件系统,全面认识Linux下一切皆文件。

一.Linux下一切皆文件 

        如何理解一切皆文件?我们都知道Linux是用C语言写的,那时候的编程思想都是面向过程。C语言是如何实现面向对象?甚至是运行时 像C++一样有多态的特性?

底层的不同的硬件,一定是对应不同的操作方法,但是这些设备都是外设,所以这些外设核心访问函数,都可以是read、write I/O,因此这些设备,都有的自己的read、write 但是它们实现方法肯定是不一样的。所以从OS角度来讲,这些设备被打开时,OS给它们创建struct file结构体,不同的外设(对象)调用自己的读写函数。这不就形成多态了吗? 

二.缓冲区

1.缓冲区概念

什么是缓冲区?从生活角度来讲,最直观的就是快递公司,假如你在北京读大学,你高中的同学在新疆读大学,有一天你同学要给你寄新疆的特产。请问你同学给你寄东西是马上就发货的吗?如果是这样快递公司早就垮了。快递公司肯定是等到不同的人寄的东西,都是要发往北京 等到一车要装满之后,才发货。 这个车就是一段内存空间

2.缓冲区意义 

 为什么要有缓冲区? 从上面例子来说就是节约成本,对OS来说也是一样,大量频繁的IO访问对OS负担是很大的,这种模式我们叫做写透模式(WT),特点就是成本高,运行慢。

对用户而言建立缓冲区,写回模式(WB)快速,成本低。提高整机利用率。

3.缓冲区在哪里 

缓冲区在哪? 我们先看一段代码看看结果

int main()
{
    //c语言提供的
    const char *s = "hello world1\n";
    const char *s1 = "hello world2\n";
    printf("hello linux\n");
    fprintf(stdout, "%s", s);
    fputs(s1, stdout);
    //os提供的
    const char *s2 = "hello world3\n";
    write(1, s2, strlen(s2));

    //创建子进程
    fork();
    return 0;
}

我们对子进程进行重定向 发现除了write只写一次,C提供的函数写入了两次这是为什么? 

首先缓冲区的刷新策略先了解一哈:

1.立即刷新

2.行刷新

3.满刷新(全缓冲)

特殊情况:

•用户强制刷新(fflush)

•进程退出

一般C库函数写入文件时是全缓冲的 而写入显示器是行缓冲。当重定向到普通文件时数据缓冲方式就由行缓冲变为了全缓冲。

•而我们放在缓冲区中的数据,就不会被立即刷新,甚至fork之后,但是进程进程退出了,会统一刷新,写入到文件中。但是创建子进程的fork()调用会复制当前进程(父进程)的状态,包括程序计数器、寄存器内容、打开的文件描述符等。因此,在fork()之后,父进程和子进程都有自己的地址空间副本,但它们的程序执行路径是相同的。

•所以当你父进程准备刷新的时候,子进程也就有了同样的 一份数据,随即产生两份数据。
write 没有变化,说明没有所谓的缓冲。
综上: printf fwrite fputs 库函数会自带缓冲区,而 write 系统调用没有带缓冲区。另外,我们这里所说的缓冲区, 都是用户级缓冲区。其实为了提升整机性能,OS也会提供相关内核级缓冲区,不过不再我们讨论范围之内。 那这个缓冲区谁提供呢? printf fwrite fputs是库函数, write 是系统调用,库函数在系统调用的上层, 是对系统 调用的“封装,但是 write 没有缓冲区,而 printf fwrite 有,足以说明,该缓冲区是二次加上的,又因为是 C,所以由C 标准库提供。

 三.文件系统

1.初识文件系统

电脑中有没有没有被打开的文件?当然有的,在哪里?磁盘。

问题一:单个文件角度,这个文件在哪里,这个文件多大?这个文件其他属性是什么?

问题二:OS层面角度,一共有多少个文件?各自属性在哪里?如何快速找到?磁盘还可以存储多少个文件?如何快速找到指定的文件?

要像彻底明白上面的两个问题 我们需要先了解磁盘的物理结构。 

 

从上图可以看出磁盘并不是像光盘那样只有一面,它像是很多层的光盘叠放在一起,每一层都有一个读写磁头。 我们在看看盘面的俯视图。

 

2. 扇区中的块组是如何工作的?

        对于磁盘的每一个盘面来说,并不是所有的区域都可以用来存储数据,可以把扇区看作是C语言的中数组。每个一扇区的存储大小一般而言都是512字节。

        所以OS就把整个磁盘拆分成无数的扇区,就变成了无数的数组。所以要找到一个文件

就只需要找到它的下标。

        对磁盘的管理,变成了对数组的管理。那OS又是如何管理这些“数组”?

首先一个磁盘太大了,在我们电脑当中有C盘和D盘、E盘。这就是传说中分区。对磁盘的管理就变成了对一个小分区的管理。对分区在进行分,分成块组分治的思想管理 请看下图。

Block Group 文件系统会根据分区的大小划分为数个 Block Group 。而每个 Block Group 都有着相同的结构组成。
超级块( Super Block ):存放文件系统本身的结构信息。记录的信息主要有: bolck inode 的总量,未使用的block inode 的数量,一个 block inode 的大小,最近一次挂载的时间,最近一次写入数据的 时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block 的信息被破坏,可以说整个文件系统结构就被破坏了。
GDT Group Descriptor Table :块组描述符,描述块组属性信息。
块位图(Block Bitmap ): Block Bitmap 中记录着 Data Block 中哪个数据块已经被占用,哪个数据块没有被占用
inode 位图( inode Bitmap ):每个 bit 表示一个 inode 是否空闲可用。
节点表 (inodeTable)点表 : 存放文件属性 如 文件大小,所有者,最近修改时间等
数据区(Data blocks):多个4KB(扇区*8)大小集合。存放文件内容

块组被分成上面的相关内容,并且写入相关的管理数据,每一个块组都这么干,整个分区就被写入到了文件系统信息。这就是你电脑和手机每次重新安装系统所对应的传说之中的格式化。 

一个文件“只”对应一个inode属性节点,inode编号。(当然不是一个文件名叫张三,万一它有小名了?)一个文件只能对应一个block吗??

当然不是,在struct inode这个结构体中定义一个int block[15] 这样的数组  这个数组下标对应就是你文件的存放block,这样就找到了文件的内容。

文件属性?inode编号不就是文件的属性吗?

这时有人要问了 一个 int block[15] 才多大,能放下一个大文件吗?

不是所有的data block,只能存放文件数据,也可以存放其他块组的块号!!大文件不就放下了吗? 

 

3. 理解软硬链接 

        

inode 和 文件名 请问找到文件的本质什么?
inode编号 -> 分区特定的bg -> inode -> 属性 -> 内容 那怎么知道inode的编号?依托目录结构
所以我们看到,真正找到磁盘上文件的并不是文件名,而是inode。 其实在linux中可以让多个文件名对应于同一个inode
看下图

使用指令:ln 创建硬链接 

 

 可以发现,在创建硬链接前,myproc.cc的引用计数是1,而创建硬链接后计数变成了2,其实硬链接的本质就是给相同的文件取别名,硬链接没有自己的inode,它和原文件的inode相同!请看下面的图片验证:

 指令:ln -s 创建软连接

 可以发现,创建的软连接是独立的一个文件,它有自己的inode,那软连接有什么用?看下图演示。

 

如果一个大型项目,你要运行别人的写的函数,可是这个可执行程序不在你的当前路径,你要运行每次都要加路径,万一这个可执行程序隐藏的很深,那不是光加路径就烦人了,这时软连接就起作用了。 

 

 软链接就如同window下的快捷方式!!!

 三.动静态库

        

• 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
• 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
•一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking
•动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚 拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

生成静态库

这是我写的两个简单函数,下面先生成.o文件

指令:g++ -c 文件名 -o 文件名.o 

第二步打包.o文件  指令:ar -rc libother.a add.o print.o

 

 这里指令太多了,直接用makefile

第三步发布  

 

 

指令:g++ main.cc -I ./other/include/ -L ./other/lib/ -l other 

 

静态库还有一种拷贝到系统环境下的方法,这里就不演示了,不推荐。

生成动态库

同时生成动态库和静态库 

 指令:g++ -c -fPIC add.cc -o add_d.o 

g++ -shared add_d.o print_d.o -o libother.so

-shared 是 g++ 编译器的一个选项,用于指示编译器生成共享对象文件(Shared Object File),这通常具有 .so 的扩展名。在Unix-like系统中,共享对象文件是一种可以被多个程序同时使用的库文件。这与静态库(通常由 ar 命令生成,具有 .a 扩展名)不同,静态库在链接时会被完整地复制到最终的可执行文件中。 当使用 -shared 选项时,g++ 会生成一个包含目标代码和重定位信息的共享对象文件。 

 

.PHONY:all
all:libother.so libother.a
libother.so:add_d.o print_d.o
	g++ -shared add_d.o print_d.o -o libother.so
add_d.o:add.cc
	g++ -c -fPIC add.cc -o add_d.o
print_d.o:print.cc
	g++ -c -fPIC print.cc -o print_d.o -std=c++11
libother.a: add.o print.o
	ar -rc libother.a add.o print.o
add.o:add.cc
	g++ -c add.cc -o add.o
print.o:print.cc
	g++ -c print.cc -o print.o -std=c++11

.PHONY:other
other:
	mkdir -p other/lib
	mkdir -p other/include
	cp -rf *.h other/include
	cp -rf *.a other/lib
	cp -rf *.so other/lib
.PHONY:clean
clean:
	rm -rf *.o *.a *.so other

 1.导入环境变量方法

运行出错了,找不到动态库 

导入环境变量:

export LD_LIBRARY_PATH=$LD_LIBART_PATH:/home/gx/linux-exercise/lesson9/uselib/other/lib

 

 2.修改配置文件

/etc/ld.so.conf.d/ 在这个路径下创建一个文件 other.conf

 

sudo vim 打开这个文件 

 

粘贴复制之后 再sudo ldconfig 

 

这时我们再./a.out就找到这个库了。

 

 3.软连接到系统库下面

指令:这里软连接要用绝对路径

sudo ln -s ~gx/linux-exercise/lesson9/uselib/other/lib/libother.so /lib64/libother.so

 

不推荐这个做法,因为我们写的这个库是没有经过官方认证的,这样会污染官方库。

下去自己试了之后就把它删除了。 

 

还有没有其他方法,当然还有的,.bashrc 这里 把我们第一点方法放在这里就行。

建议不要做!!!

下节预告进程间通信 ,关注我带你学习更多Linux知识。

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS实战开发-实现自定义弹窗

介绍 本篇Codelab基于ArkTS的声明式开发范式实现了三种不同的弹窗,第一种直接使用公共组件,后两种使用CustomDialogController实现自定义弹窗,效果如图所示 相关概念 AlertDialog:警告弹窗,可设置文本内容和响应回调…

Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(三)

概览 承接上一篇博文: Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(二)我们在其中讨论了如何使用第三方强大通用的钩子库 SwiftHook 来协助我们完成 NSObject 构造器 init 的 SWIZZ 操作。我们还讨论了为什么用 print 打印对象信息时会发生崩溃…

在Windows系统上安装多个 Nodejs

前言 在Windows系统安装Nodejs 在Windows系统上安装多个 Nodejs v14.16.1安装位置 D:\sde\nodejs\node-v14.16.1-win-x64 v16.20.2安装位置 D:\sde\nodejs\node-v16.20.2-win-x64 v18.20.0安装位置 D:\sde\nodejs\node-v18.20.0-win-x64 v20.12.0安装位置 D:\sde\nod…

YOLOv9改进策略 :neck优化 | 路径融合GFPN,小目标到大目标一网打尽 | 轻骨干重Neck的轻量级目标检测器GiraffeDet

💡💡💡本文改进内容:设计了一种新的路径融合GFPN:包含跳层与跨尺度连接,改进思路来自ICLR2022 GiraffeDet的核心思想。 💡💡💡GFPN和六个检测头结合,这种跳层…

集体出走的Stability AI 发布全新代码大模型,3B以下性能最优,超越Code Llama和DeepSeek-Coder

Stability AI又有新动作!程序员又有危机了? 3月26日,Stability AI推出了先进的代码语言模型Stable Code Instruct 3B,该模型是在Stable Code 3B的基础上进行指令调优的Code LM。 Stability AI 表示,Stable Code Instru…

【python】flask执行上下文context,请求上下文和应用上下文原理解析

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

2024河北石家庄矿业矿山展览会|河北智慧矿山展会|河北矿博会

2024中国(石家庄)国际矿业博览会      时间:2024年7月4-6日 地点:石家庄国际会展中心.正定      随着全球经济的持续增长和矿产资源需求的不断攀升,矿业行业正迎来前所未有的发展机遇。作为矿业领域的盛会&…

3.28C++

复数类的实现&#xff0c;写出三种构造函数&#xff0c;算术运算符、关系运算符、逻辑运算符重载尝试实现自增、自减运算符的重载 #include <iostream> using namespace std; class Num {int rel; //实部int vir; //虚部 public:Num():rel(2),vir(1){}Num(int rel,…

确保未来安全:应对云安全的复杂性

云是业务运营的重要组成部分&#xff0c;它改变了组织扩展、创新和适应的方式。然而&#xff0c;其影响力日益增长的广度和深度不仅仅局限于商业领域。云环境是我们日常生活中不可或缺的一部分&#xff0c;负责存储和传输全球平民最敏感的数据。随着大量企业和个人利用云&#…

【C语言】编译和链接----从源代码到可执行程序的转换【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作揭秘&#xff1a;C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 欢迎来到本篇博客&…

最小化安装Kubesphere报错问题解决方法

最小化安装Kubesphere报错: TASK [preinstall : Stop if defaultStorageClass was not found] ****************** fatal: [localhost]: FAILED! > {"assertion": "\"(default)\" in default_storage_class_check.stdout", "changed&qu…

数据结构进阶篇 之 【二叉树链序存储】的整体实现讲解

封建迷信我嗤之以鼻&#xff0c;财神殿前我长跪不起 一、二叉树链式结构的实现 1.二叉树的创建 1.1 手动创建 1.2 前序递归创建 2.二叉树的遍历 2.1 前序&#xff0c;中序以及后序遍历概念 2.2 层序遍历概念 2.3 前序打印实现 2.4 中序打印实现 2.4 后序打印实现 2.…

SnapGene 5 for Mac 分子生物学软件

SnapGene 5 for Mac是一款专为Mac操作系统设计的分子生物学软件&#xff0c;以其强大的功能和用户友好的界面&#xff0c;为科研人员提供了高效、便捷的基因克隆和分子实验设计体验。 软件下载&#xff1a;SnapGene 5 for Mac v5.3.1中文激活版 这款软件支持DNA构建和克隆设计&…

Linux_进程概念_冯诺依曼_进程概念_查看进程_获取进程pid_创建进程_进程状态_进程优先级_环境变量_获取环境变量三种方式_3

文章目录 一、硬件-冯诺依曼体系结构二、软件-操作系统-进程概念0.操作系统做什么的1.什么叫做进程2.查看进程3.系统接口 获取进程pid- getpid4.系统接口 获取父进程pid - getppid5.系统接口 创建子进程 - fork1、手册2、返回值3、fork做了什么4、基本用法 6.进程的状态1、进程…

【Java扫盲篇】String、String Buffer和String Builder的区别

你在面试时&#xff0c;面试官让你讲讲String String Buffer String Builder的区别&#xff0c;你是否能流畅的、完整的叙述出他们三者的区别? ✍先说结论 相同点&#xff1a; 他们的底层都是由char数组实现的。不同点&#xff1a; String对象一旦创建&#xff0c;是不能修…

PCL点云处理之M估计样本一致性(MSAC)平面拟合(二百三十六)

PCL点云处理之M估计样本一致性(MSAC)平面拟合(二百三十五六) 一、算法介绍二、使用步骤1.代码2.效果一、算法介绍 写论文当然用RANSAC的优化变种算法MSAC啊,RANSAC太土太LOW了哈哈 MSAC算法(M-estimator Sample Consensus)是RANSAC(Random Sample Consensus)的一种…

初入C++

C 编译时的查找&#xff1a; 先到函数局部域里查找到全局域找 局部域和全局域会改变生命周期。 命名空间域不会影响变量的生命周期。 默认情况下不会到命名空间域去找。(命名空间域内的变量的生命周期是全局的&#xff0c;及不会出命名空间就销毁) 在不同的作用域可以定义同…

Linux系统-----------MySQL 数据类型

目录 MySQL 数据类型 一、数值类型 二、日期和时间类型 三、字符串类型 &#xff08;1&#xff09;CHAR类型 &#xff08;2&#xff09;VARCHAR类型 &#xff08;3&#xff09;CHAR和VARACHAR的比较及其应用场景 MySQL 数据类型 MySQL 中定义数据字段的类型对你数据库的…

OC对象 - Block解决循环引用

文章目录 OC对象 - Block解决循环引用前言1. 循环引用示例1.1 分析 2. 解决思路3. ARC下3.1 __weak3.2 __unsafe_unretained3.3 __block 4. MRC下4.1 __unsafe_unretain....4.1 __block 5. 总结5.1 ARC下5.2 MRC下 OC对象 - Block解决循环引用 前言 本章将会通过一个循环引用…

深入解析RSA算法原理及其安全性机制

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 一、RSA算法简介二、RSA算法原理2.1 背景与数学基础2.2 密钥生成2.3 加密过程2.4 解密过程 三、安全性考虑四、RSA的使用五、…