【Linux】磁盘结构、文件系统、软硬链接、动静态库链接
文章目录
- 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库。)
本章完~
相关文章:

【Linux】磁盘结构、文件系统、软硬链接、动静态库链接
文章目录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 动静态库的加载下面了解到&…...

交换机电口、光口、网络速率的基本概念总结
电口和光口千兆网 & 万兆网:POE:包转发率:背板带宽/交换容量:)电口和光口 电口: 电口也即RJ45口,插双绞线的端口(网线),一般速率为10M或100M,即为百兆工…...
【面试题 05.02. 二进制数转字符串】
来源:力扣(LeetCode) 描述: 二进制数转字符串。给定一个介于0和1之间的实数(如0.72),类型为double,打印它的二进制表达式。如果该数字无法精确地用32位以内的二进制表示࿰…...
webpack - webpack的基本使用和总结
文章目录1,webpack概念2,为什么学webpack3,webpack特点4,相对于其他工具优点5,准备工作6,webpack的核心介绍7,webpack使用 - 打包js代码8,打包css代码9,生成html文件10&a…...

【蓝桥杯嵌入式】定时器实现按键单击,双击,消抖以及长按的代码实现
🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都在这儿哦,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 - 蓝…...
基于SSM的Javaweb爱心扶贫捐赠系统
文章目录 项目介绍主要功能截图:后台登录首页个人中心用户管理扶贫物资管理扶贫产品管理留言板管理前台前台首页扶贫产品新闻资讯留言板部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,…...

Spring Cloud(微服务)学习篇(三)
Spring Cloud(微服务)学习篇(三) 1 nacos中使用openFeign(调用方式)实现短信发送 1.1 在shop-sms-api中创建com.zlz.shop.sms.api.service/vo/dto/util,目录结构如下所示 1.2 在pom.xml(shop-sms-api)中加入如下依赖 <dependencies><dependency><groupId>…...

一文带你吃透JSP,增删改查实战案例详细解读
文章目录前言JSP 概述JSP快速入门搭建环境导入JSP依赖创建 JSP 页面编写代码测试JSP原理JSP 脚本实战案例JSP缺点发展阶段EL 表达式概述实战案例域对象JSTL 标签用法1用法2前言 不得不说,JSP 现在已经是一门十分老旧的技术了,学习编程时,不仅…...

taobao.item.propimg.upload( 添加或修改属性图片 )
¥开放平台基础API必须用户授权 添加一张商品属性图片到num_iid指定的商品中 传入的num_iid所对应的商品必须属于当前会话的用户 图片的属性必须要是颜色的属性,这个在前台显示的时候需要和sku进行关联的 商品属性图片只有享有服务的卖家(如&a…...

TDEngine集群监控组件安装配置(Telegra+Grafana方案)
Tdengine的监控指标包括以下几个方面: 系统指标:CPU使用率、内存使用率、磁盘空间、网络流量等。数据库指标:连接数、查询数、写入数、读取数等。SQL指标:执行时间、执行计划、索引使用情况等。集群指标:节点状态、数…...
【定位】高德地图wifi定位接口使用效果实践
高德地图wifi定位接口使用效果实践 背景 目的是基于高德地图wifi定位接口实现在高德地图上展示终端设备的位置和轨迹。 原理 为了将原理阐述的稍微直白一点,特意使用UML图表产生下面的一个序列图: #mermaid-svg-iHgWizHiUSRqCWdF {font-family:"trebuchet ms",…...

Nacos注册中心
目录 认识和安装Nacos 启动方式 Nacos快速入门 提示 Nacos服务分级存储模型 服务跨集群调用问题 管理端设置策略 总结 Nacos环境隔离 如何创建 使用方式 编辑 总结 Nacos注册中心分析 临时实例和非临时实例 定义 配置方式 总结 认识和安装Nacos Nacos是Sp…...
Liunx常用命令总结
常用命令arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT /dev/sda 在磁盘上执行测试性读取操作 cat /proc/cpuinfo …...

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

【RocksDB】Ubuntu20.04下编译rocksdb
前言: 我在刚学rocksdb的时候是在2022年,但是网上的资源很少,查了好久才把rocksdb安装成功,在这里向大家分享一下我的经历,安装过程中也报了很多错误,希望大家不要迷路 首先 在虚拟机里面安装依赖的包以…...
这可能是Spring Boot Starter 讲的最清楚的一次了
Spring Boot Starter 是 Spring Boot 中非常重要的一个功能,它可以帮助开发人员快速集成各种第三方库和框架。本文将从 Spring Boot Starter 的基本概念入手,深入讲解 Spring Boot Starter 的实现原理及其应用场景。 一、Spring Boot Starter 的概念 S…...

activiti7执行流程详解
什么是工作流? 官方定义:工作流是将一组任务组织起来以完成某个经营过程:定义了任务的触发顺序和触发条件,每个任务可以由一个或多个软件系统完成,也可以由一个或一组人完成,还可以由一个或多个人与软件系统…...
iframe页面传值取值
业务:目标界面的是用原生js写的 , 被镶嵌到vue平台上 , 现在要求vue点击跳转的时候 ,要附带上值 ,让原生界面获取到值 , 完成页面设置查询。 想法 : vue跳转,使用this.$route.qu…...

2023年2月安全事件盘点
一、基本信息 2023年2月安全事件共造成约3796万美元损失,相较于上个月,安全事件数量与损失金额都有显著上升,其中Platypus Finance闪电贷攻击为单次利用损失之最高达850万美元。本月RugPull数量基本与上月持平,损失金额占比显著降…...

2023上海国际电商物流包装产业展览会相约上海
2023年7月5-7日 | 上海新国际博览中心 同期举办:2023上海国际快递物流产业博览会 指导单位:上海市邮政管理局 中国快递协会 主办单位:上海市快递行业协会 上海市仓储与配送行业协会 上海市物流协会 承办单位:上海信世展览服务有…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...