【Linux】磁盘结构、文件系统、软硬链接、动静态库链接

news2024/11/25 20:17:28

文章目录

    • 1、磁盘结构
      • 1.1 磁盘的物理结构
      • 1.2 磁盘的存储结构
      • 1.3 磁盘的逻辑结构
    • 2、文件系统
      • 2.1 4KB加载到内存
      • 2.2 文件系统结构
    • 3、软硬链接
      • 3.1 软链接
      • 3.2 硬链接
    • 4、动静态库
      • 4.1 什么是库?
      • 4.2 静态库和静态库链接
      • 4.3 动态库和动态库链接
      • 4.4 动静态库的加载

下面了解到,操作系统是如何管理放在磁盘中的未打开文件的。

1、磁盘结构

磁盘不仅是一种外设,还是唯一的一个机械结构的外设,所以相对其它硬件来说很慢,但是它可以存储大量的数据,下面看它的具体结构。

1.1 磁盘的物理结构

磁盘主要由盘面、磁头等构成。
值得注意的是:
磁盘的盘面有两面,两面都可以读写数据,一个磁盘有多个盘面。

磁盘的磁头,每个盘面的一面都对应着一个磁头,并且磁头和盘面是没有挨着的。(这点不像老式DVD读光盘是挨着的)

磁盘的存储原理在大概上
盘片中有很多微小的磁块,这些磁块拥有着南北极,存储对应的二进制01。磁头对磁块进行放磁,使得磁块进行转向,通过南北极转换来进行01二进制标识。

在这里插入图片描述

1.2 磁盘的存储结构

在盘面上,每一圈对应着一个磁道,磁道又分为多个扇区。

磁头是共进退的!磁头在定位对应盘面的时候,整体是共进退的,所以磁头共同在同一个磁道上找,整体就成了柱面。

对于扇区来说,靠圆心的扇区面积小,离圆心远的扇区面积大,但是每个扇区都是512byte,密度不一样。(当然也有一样的,这里是一般的。)

磁盘的寻址方式的基本字节是512byte,一个扇区大小。

那么磁盘中如何定位一个扇区呢?
先在整个柱面(Track)定位哪一个磁道,再定位磁头(head)看在哪个盘面上,最后定位在哪个扇区(sector)上。综上这个方法也叫CHS。

磁头来回摆动确定在哪个磁道,盘面高速旋转,让磁头定位扇区。
所以磁盘效率就看在高速旋转中,在能读写数据的前提,多少转每秒,即每秒多少读写次数。
这里是引用

1.3 磁盘的逻辑结构

磁盘在物理上的存储结构是圆形的,如果将其抽象拉直,就变成了对数组的管理。

在数组上,分为多个大的磁道,磁道中又分了多个扇区,所以只要通过简单的除与除余就能得到一个扇区的位置。这种定位也被称为LBA(logical block address)

在这里插入图片描述

这种方式相较于CHS法有什么好处吗?
1、首先这样肯定是更加方便管理的。
2、其次,OS不想和硬件进行强耦合,这个方式在OS中可以不仅限于管理磁盘,也能用在其它硬件上。

2、文件系统

2.1 4KB加载到内存

首先,前面说过磁盘在读取时基本单位是512byte,但是对于OS来说一次读这么点还是太少了,OS就有自己的读取策略,一次读取多个扇区,比如1KB、2KB、3KB、4KB(现在主流都是一次4KB)。

在一次读多个扇区下,哪怕是访问一个字节的量,也要将4KB空间load到内存。

这种方式,也有部分因为局部性原理
当计算机访问数据,附近的数据也大概率被访问到。加载更多的数据能增加数据IO的效率,局部性原理的存在也能增加数据的命中率,一定上减缓了更多的IO过程,本质是一种数据预加载,空间换时间!

内存也因此,被划分成了多个4KB大小的空间,这个空间称为页框,一个4KB大小的块被称为页帧。
在这里插入图片描述

2.2 文件系统结构

磁盘是很大的,为了更好的管理,需要分区,分组 (与国家划分省、市是一样的),但磁盘有一点不太的是,各个分区分组的管理方式是一样的。

这里是引用

  • 超级块(Super Block):存放文件系统本身的结构信息,有属性信息、磁盘布局和资源使用情况等信息。超级块属于整个分区,分区有一定比率分组都有对应的超级块,多存在意味着备份,保存在不同分组,若某一个分组的文件系统坏了,可以用其它分组的超级块恢复。
  • 块组描述符(GDT):存放分组的宏观属性信息,如一共有多少个inode,有多少数据块,以及用了多少,多少没被用。

首先,一个文件 = 内容 + 属性,并且文件的内容和属性是分开存储的!

其中文件内容保存在数据块中(Data Blocks),文件属性保存在Inode中
Inode(ext3-128byte ext4-256byte)包括一个文件的几乎所有属性,文件名不在Inode中,并且每个文件都有属于自己的Inode。

通过ls -li 带上-i 可以查看每个文件对应的Inode。
在这里插入图片描述

  • Inode Table 保存了分组内部所有可用(使用和未使用)的inode。
  • Data blocks 保存的是分组内部所有文件的数据块(4KB为单位)

为了区分Inode或者Data blocks 中哪些被使用哪些没被使用。

  • Inode Bitmap 中inode通过位图结构,一个Inode对应一个bit位,比如第一个bit位代表1号inode,1代表被用,0代表没被占用。
  • Block bitmap 数据块对应的位图结构也一样,比如10000个块,对应10000个bit位,被使用的块由0置1,清除就由1置0。

当想查找一个文件时,统一使用的是: inode编号
(并且,Inode在不同组,有多套inode,比如0组是1000开始的,1组是10000开始的,所以拿到一个inode也很好定位)

值得注意的是:我们使用的是文件名,不是inode,这是因为目录也是个文件,目录的数据块存的是目录里文件的inode和文件名的映射,所以通过文件名再到映射的inode,就可以找到了。

这也说明,一个目录下不能有同名文件。
也说明,如果要在目录创建一个文件,必须有目录的写入权限,需要在目录代码块中建立inode和文件名的映射。


那如何找到文件内容呢?数据块这么多,怎么知道是你的?

在inode属性中有一个blocks数组,其中0-11一般指向一个数据块,如果文件只有几个数据块,直接通过下标定位对应数据块就行了。

一般从12、13、14开始,比如12指向的数据块,里面保存着其它数据块的地址。13、14指向的数据块里面指向有多层都是地址,这样就可以指向很多给数据块。

在这里插入图片描述

那么如何删除文件呢?
直接通过inode找到对应代码块,将代码块对应的block bitmap中1置0,再将inode bitmap中对应的inode置0就行。
(这就说明,删除文件只是把bitmap中至0,对应数据块的数据还是在的)

如果误删文件,只是清bit位,恢复文件Inode bitmap至1,inode table中找数据块映射,将对应block bitmap中至1,就能找回文件,所以如果误删文件,最好就是什么也别做,怕将原来数据块覆盖。

3、软硬链接

3.1 软链接

首先通过ln -s 文件名 生成软链接文件名 ,比如下面创建一个soft_file.link。
在这里插入图片描述

软链接的原理:
软链接是一个独立的文件,只不过这个文件保存着被链接文件的地址。
当被链接文件删除时,这个地址也就无效了,简单来说软链接生成的文件就是一个快捷方式
(可以看到,软链接生成的文件有自己的inode)
在这里插入图片描述
在这里插入图片描述

通过unlink 链接文件名 或者 rm 就可以删除链接文件取消软链接。

3.2 硬链接

硬链接通过 ln 被链接文件名 生成链接文件名,比如:
(可以看到,生成的链接文件和被链接文件用的是同一个inode
在这里插入图片描述

因为目录中存在两个不同的文件名映射同一个inode,inode里也会有一个计数器,计数有多少个文件名和inode映射关系(引用计数:硬链接数)
如果删除了mytest.txt,仅仅减少一个引用计数和一个对应关系。
只有当引用计数为0时,位图才清0,文件才删除。
(下面两个文件名链接到同一个inode,所以各自硬链接数为2)
在这里插入图片描述
在这里插入图片描述

硬链接的作用:

首先,对于一个普通文件,硬链接数为1,因为只有自身文件名和inode具有映射关系。  
一个目录默认硬链接为2,因为本身和inode有映射关系,而在目录中 .
作为一个文件代表当前目录和目录有一样的inode,是目录的硬链接。

在这里插入图片描述

下面又在empty目录里再创一个目录empty2,此时empty的硬链接数为3,这个empty2中的…文件是empty目录的硬链接。
在这里插入图片描述

综上,硬链接让文件系统能够方便的访问上下文。

下面看到的一个问题:

Linux 为什么不允许用户(包括root)给目录建立硬链接呢?
.和… 不就是给目录建立的硬链接吗?
在这里插入图片描述

其实,这时操作系统给的保护措施,操作系统只运行自己建立,不允许使用者建立。
怕的就是这样:
在这里插入图片描述

4、动静态库

4.1 什么是库?

首先得了解一下编译的过程及命令

-o 指明形成的临时文件名  .o文件结尾的叫做可重定义目标二进制文件。
gcc -E test.c -o test.i 预处理
gcc -S test.i -o test.s 编译 转换成汇编语言
gcc -c test.s -o test.o 汇编转换成不可执行的二进制文件
gcc test.o -o mytest 链接


分别记忆成ESc和iso

在实际生成一个文件可以不用从预处理写起,比如生成一个不可执行的二进制文件可以直接gcc -c 指定文件名
在这里插入图片描述


如果不想给对方源代码(.c)文件,只需要给对方编译好的.o可重定义目标二进制文件,再包括对应头文件就行。 (.o文件包括方法的实现,.h文件包括有什么方法)

将所有".o文件",打一个包,给对方提供一个库文件即可!
综上库其实就是多个.o文件的集合。

4.2 静态库和静态库链接

生成静态库:
比如:ar -rc libmymath.a add.o sub.o
(rc表示replace and create)
将add.o和sub.o打包成libmymath.a静态库文件。
在这里插入图片描述

查看静态库中的目录列表:
比如:ar -tv libmymath.a
(-t 列出静态库中的文件,v:verbose 详细信息)
在这里插入图片描述

除了要静态库文件还要对应匹配的头文件,将库文件和.h打包起来,并且可以通过压缩包让别人使用,而安装本质就是将头文件和.a文件拷贝到系统特定路径。
(特定的头文件就是放在user/include下,特定动静态库就是放在/lib64下)
在这里插入图片描述

这里的测试文件就不放在系统特定文件中,这里可以自己创建一个mylib。
再将静态库文件和头文件打包,让使用者只能获取函数使用。
在这里插入图片描述


接下来就是链接库,生成可执行文件的过程

值得注意的是,平常程序生成可执行文件的命令简略是因为默认指明了库文件的路径以及头文件的路径。
这里的链接就需要自己指明各自的库路径。
gcc -o mymath main.c -I ./mylib/include -L ./mylib/lib -l mymath
(其中-o指明生成的可执行文件名,-l 指明include文件路径,-L 指明lib文件路径,-l 指明库文件名) 最重要的是库文件名其实是libmymath.a,但是在链接时需要去掉lib和后缀.a才是真正文件名。
在这里插入图片描述

测试目标文件生成后,静态库删掉,程序照样可以运行

4.3 动态库和动态库链接

生成动态库:
比如:gcc -fPIC my_add.c 生成与位置无关码的.o文件。
生成多个.o文件后。
通过gcc -shared -o libmymath.so my_add.o my_sub.o生成动态库文件。

生成动态库文件后,将库文件和头文件进行打包。
打包后,如果正常链接也是会出错的,意料之中,因为没有指明库文件路径和头文件路径

在这里插入图片描述

指明路径后,成功生成可执行文件,但是运行却发生了错误。
通过ldd(列出动态库依赖关系)看到libmymath.so 动态库的地址找不到。

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

为什么会找不到动态库?

因为上述操作只告诉了gcc库文件路径和名称,但是程序在gcc编译完后,就和gcc没关系了,变成进程和系统的关系了,所以也要告诉OS和shell库文件的路径和名称。
(一般动态库也是在lib64下的,我的库没有在系统路径下,所以OS无法找到)

OS搜索库,除了放在特定目录下,还可以在环境变量中搜索
比如:echo $LD_LIBRARY_PATH
将动态库绝对路径放入:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yzh/dslib/test/mylib/lib/
在这里插入图片描述
这种方法如果用户退出就失效了。

如果要永久有效的话。
只要访问cd /etc/ld.so.conf.d/这个路径,在这个路径下创建一个配置文件,然后将我们的动态库的绝对路径放入任意一个配置文件当中就可以了。
sudo创建一个配置文件,再sudo vim打开放入路径。
放入后sudo ldconfig 更新配置文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后一种方式就是通过软链接,在自定义路径下创建一个动态库的快捷方式。
在这里插入图片描述

4.4 动静态库的加载

静态库的加载
静态库的加载很简单,静态库的代码在编译期间直接拷贝到程序的代码区,未来这部分代码,必须通过相对确定的地址位置来进行访问,这也使得这部分代码在编译期间就有了一套虚拟地址,可以和虚拟地址空间进行适配。(绝对编址方案)

动态库的加载
动态库是将指定函数的地址,写入到可执行程序中。

1、动态库中的函数,在编译期间,是以一种start:偏移量方式定位的,函数只需要填一个偏移量地址。start就是ldd指令显示的动态库起始地址,偏移量是相对start的,所以在gcc -fPIC 形成与位置无关码,就是想用偏移地址,不是绝对编地址。

2、当程序加载到内存,并且走到函数时,这个时候就会停下来,访问动态库(所以也是为什么要让OS看到动态库),然后将动态库需要的部分加载到内存中,映射到共享区,这个时候就获得了库的起始地址!这样函数就可以通过偏移量访问对应函数。

这里是引用


综上:
1、如果有很多个程序并且有很多用着同一份函数,如果链接的是静态库,就有着相同份的函数加载到内存,如果链接动态库就只需要加载一份函数到内存,能很好的节省资源。
2、其实gcc是默认建议是动态链接的,一个可执行文件如果链接了很多个库,有静态和动态的,多个库是一个一个链接的,如果是动态库就动态链接,静态就静态链接,但是如果有一个动态库,那么整个链接就是动态链接。(这也是为什么静态链接后,查看文件链接类型还是动态链接,因为还动态链接了C库。)
在这里插入图片描述


本章完~

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

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

相关文章

python GUI图形化编程-----wxpython

一、python gui(图形化)模块介绍: Tkinter :是python最简单的图形化模块,总共只有14种组建 Pyqt :是python最复杂也是使用最广泛的图形化 Wx :是python当中居中的一个图形化,学习结构很清晰 Pywin :是pyth…

Qt界面美化之自定义qss样式表

原生的QT界面不好看,有时候需要根据美工的设计图修改样式。如果使用QML的话搞界面是快,但是QML有点儿吃内存,有时简单的功能还是用传统c的widget方便些。好在有qss,传统界面也可以美化的。QSS称为Qt Style Sheets也就是Qt样式表&a…

项目设计模式和规范

1、责任链模式 自己的理解:避免发生方与接收方解耦 优点:①降低发送方与接收方的耦合 ②简化他们对象 ③方便扩展新增 处理者 缺点:①不方便排错 ②性能问题,且使用不当容易搞出死循环 应用场景:拦截器 Interceptor和过滤器 filter:符合模式的进行拦截或者过滤到,然…

华为云服务器安全注意事项

使用华为云服务器搭建集群的时候不能像我们平时使用虚拟机克隆那样随意(我指的是后期使用),要留意安全问题,防止被病毒攻击 注意事项: 1.root用户和创建的普通用户密码要设置复杂一些,不能123456或者00000…

腾讯云服务器租用报价表新鲜出炉(轻量和CVM价格)

腾讯云服务器分为轻量应用服务器和云服务器CVM,CVM为专业级云服务器,适用于企业级如科学计算、集群应用、高容灾等使用场景;轻量应用服务器适用于个人博客简单的Web应用或测试环境使用。 腾讯云服务器租用价格表2023新版报价出炉&#xff0c…

页面状态码的含义

使用互联网产品或服务的过程中,会遇到网页报错的情况, 比如404、505等,具体这些数字有什么含义呢?本文基本涵盖了99%的报错情况,可供大家查询使用。 状态码的定义 状态码一般是由3位数字和原因短语组成的&#xff08…

10 种顶流聚类算法 Python 实现(附完整代码)

聚类或聚类分析是无监督学习问题。它通常被用作数据分析技术,用于发现数据中的有趣模式,例如基于其行为的客户群。 有许多聚类算法可供选择,对于所有情况,没有单一的最佳聚类算法。相反,最好探索一系列聚类算法以及每…

MWC 2023 | 美格智能合资公司联懂格智重磅发布多款5G+AIoT系列通信产品

2月27日下午,美格智能与联想懂的通信携手设立的合资公司——广州联懂格智技术有限公司亮相西班牙巴塞罗那世界移动通信MWC大会,并发布多款5GAIoT系列通信产品。▲联想集团副总裁、联想懂的通信CEO王帅博士(右三)美格智能CEO杜国彬…

【C++】C++11 新特性

目录 1.列表初始化 1.1. C98中使用{}初始化的问题 1.2. 内置类型的列表初始化 1.3. 自定义类型的列表初始化 2. 变量类型推导 2.1. 为什么需要类型推导 2.2. decltype类型推导 2.2.1 为什么需要decltype 2.2.2. decltype 3. 对默认成员的控制(default、delete) 3.1. …

第四阶段15-关于权限,处理解析JWT时的异常,跨域请求,关于Spring Security的认证流程

处理解析JWT时的异常 由于解析JWT是在过滤器中执行的,而过滤器是整个服务器端中最早接收到所有请求的组件,此时,控制器等其它组件尚未运行,则不可以使用此前的“全局异常处理器”来处理解析JWT时的异常(全局异常处理器…

华为机试题:HJ97 记负均正(python)

文章目录(1)题目描述(2)Python3实现(3)知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…

MySQL表的增删查改(进阶)

所有操作:主要讲了数据库的约束,表之间的关系,新增,聚合查询,联合查询等内容。是一篇博客所有操作的记录。 844d186 风夏/mysql_learning - Gitee.com数据库约束1.1 约束条件not null -指定某个列不能储存null值。un…

17、二维图形绘制

目录 (一)plot绘图指令 (1)plot(x,y) (2)plot(y)。 (3)plot(z)。 (4)plot(A)。 (5)plot(x,A)。 (6)plo…

【C++】纯虚函数、纯虚析构

纯虚函数语法:virtual 返回值类型 函数名(参数列表) 0纯虚函数的作用:不用定义!在多态中,通常父类中虚函数的实现是无意义的(因为主要用子类重写的,父类只是为了派生子类当做一个类族的顶层出现&#xff0…

如何才能监控查看出注册表更改情况,本地组策略设置更改了哪些注册表对应值?

环境: Win11 专业版 HP480G7 Windows Sysinternals Suite 问题描述: 如何才能监控查看出注册表更改情况,本地组策略设置更改了哪些注册表对应值? 解决方案: 1.下载Windows Sysinternals Suite,解压找到ProcessMonitor 打开 2.先按ctrl+e capture 进行捕获监控 …

MRI结构像自定义脑部ROI-基于FSL

FSLmaths创建ROI 1.软件准备 在linux下安装好FLS,安装教程见下方视频。命令行输入FSL打开 选择FSLeyes 2.准备模板 从标准库目录里选择一个想创建的ROI的模板,打开看一下 我这里选择MNI152_2mm的模板,因为1mm的电脑会内存溢出 3.准备坐标点…

【剑指offer】JZ7 重建二叉树、JZ9 用两个栈实现队列

\描述: 给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。 思路: 题上给了我们前序遍历(根 …

信息发布小程序【源码好优多】

简介 信息发布小程序,实现数据与小程序数据同步共享,通过简单的配置就能搭建自己的小程序。,基于微信小程序开发的小程序。 这个框架比较简单就是用微信原生开发技术进行实现的,可以用于信息展示等相关信息。其中目前APP比较多&am…

瓜子大王稳住基本盘,洽洽食品做对了什么?

2月24日,洽洽食品披露2022年业绩快报,公司预计实现营收总收入68.82亿元,同比增长14.98%, 实现归母净利润9.77 亿元,同比增长5.21%,业绩基本符合市场预期。来源:洽洽食品2022年度业绩快报2022年,瓜子大王洽洽…

d3 tree 实现双向动画树总结

使用d3.js 实现双向tree,并实现节点展开收起动画。 使用svg 绘制。 效果图 d3 d3可与快速选择批量的节点。类似jquery一样可选择元素并更改其属性值。 选择节点并设置属性 import * as D3 from d3; let svg D3.select(.tree).attr("width", 800).att…