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

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

⏩专栏分类: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.og++ -shared add_d.o print_d.o -o libother.so
add_d.o:add.ccg++ -c -fPIC add.cc -o add_d.o
print_d.o:print.ccg++ -c -fPIC print.cc -o print_d.o -std=c++11
libother.a: add.o print.oar -rc libother.a add.o print.o
add.o:add.ccg++ -c add.cc -o add.o
print.o:print.ccg++ -c print.cc -o print.o -std=c++11.PHONY:other
other:mkdir -p other/libmkdir -p other/includecp -rf *.h other/includecp -rf *.a other/libcp -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.hqwc.cn/news/575968.html

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

相关文章

Redis、Mysql双写情况下,如何保证数据一致

Redis、Mysql双写情况下,如何保证数据一致 场景谈谈数据一致性三个经典的缓存模式Cache-Aside Pattern读流程写流程 Read-Through/Write-Through(读写穿透)Write behind (异步缓存写入) 操作缓存的时候,删除…

Mac添加和关闭开机应用

文章目录 mac添加和关闭开机应用添加开机应用删除/查看 mac添加和关闭开机应用 添加开机应用 删除/查看 打开:系统设置–》通用–》登录项–》查看登录时打开列表 选中打开项目,点击“-”符号

excel 提取数字字符混合文本中的数字(快捷键ctrl+e)

首先,已知A列数据,在B1单元格输入A列中的数据,如3*4*6 第二部:全选对应的B列,然后: ctrld 批量复制 CTRLE 智能复制 由此可见,智能提取汉字与数字混合中的数字方法 。若想分别提取3个数字&am…

【ONE·基础算法 || 分治·快排并归】

总言 主要内容:编程题举例,理解分治的思想(主要是对快排、并归的应用)。       文章目录 总言1、基本介绍2、颜色分类(medium)2.1、题解 3、快速排序(medium)3.1、题解&#xff…

2024年最新阿里云服务器价格表2核2G、2核4G、4核8G、8核16G等配置报价

2024年阿里云服务器优惠价格表,一张表整理阿里云服务器最新报价,阿里云服务器网aliyunfuwuqi.com整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单,大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新…

IntelliJ IDEA中遇到的“cannot access java.lang.String“错误及其解决方案(day8)

intelliJ 今天遇到使用intelliJ遇到了一个新错误,有问题就解决问题是一个程序员最基本的修养,如下: 在上面的代码中,我使用了this.这个关键字,发现出现了以上问题,找了一些资料,不是很明白&am…

【二叉树】Leetcode 98. 验证二叉搜索树【中等】

验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例1&a…

Unity照片墙简易圆形交互效果总结

还要很多可以优化的点地方,有兴趣的可以做 比如对象的销毁和生成可以做成对象池,走到最左边后再移动到最右边循环利用 分析过程文件,采用Blender,资源已上传,可以播放动画看效果,下面截个图: …

Redis开源协议变更!Garnet:微软开源代替方案?

Garnet:微软开源的高性能替代方案,秉承兼容 RESP 协议的同时,以卓越性能和无缝迁移能力重新定义分布式缓存存储! - 精选真开源,释放新价值。 概览 最近,Redis修改了开源协议,从BSD变成了 SSPLv…

主流公链 - Filecoin

探索Filecoin:去中心化存储网络 1. Filecoin简介 Filecoin是一个去中心化的存储网络,旨在通过区块链技术实现全球性的分布式文件存储和检索市场。Filecoin允许用户将文件存储在网络中的节点上,并通过加密、分片和复制等技术保证数据的安全性…

八大技术趋势案例(虚拟现实增强现实)

科技巨变,未来已来,八大技术趋势引领数字化时代。信息技术的迅猛发展,深刻改变了我们的生活、工作和生产方式。人工智能、物联网、云计算、大数据、虚拟现实、增强现实、区块链、量子计算等新兴技术在各行各业得到广泛应用,为各个领域带来了新的活力和变革。 为了更好地了解…

【数学符合】

数学符合 ■ ∑ ■ ∑