手机网站 宽度网站在浏览器的图标怎么做

当前位置: 首页 > news >正文

手机网站 宽度,网站在浏览器的图标怎么做,seo站内优化教程,重庆建筑工程安全信息网文件系统软硬连接动静态库 1.理解文件系统1.1磁盘的物理结构1.2磁盘的存储结构1.3磁盘的逻辑结构1.4文件系统 2.软硬链接2.1什么是软硬链接2.2软硬链接的作用 3.动静态库3.1什么是库3.1静态库和静态链接3.2动态库和动态链接3.2.1通过环境变量找到动态库路径3.2.2把动态库拷贝到… 文件系统软硬连接动静态库 1.理解文件系统1.1磁盘的物理结构1.2磁盘的存储结构1.3磁盘的逻辑结构1.4文件系统 2.软硬链接2.1什么是软硬链接2.2软硬链接的作用 3.动静态库3.1什么是库3.1静态库和静态链接3.2动态库和动态链接3.2.1通过环境变量找到动态库路径3.2.2把动态库拷贝到默认路径下3.2.3添加到配置文件中3.2.4建立软链接 3.3动静态库的加载原理3.3.1静态库加载原理3.3.2动态库加载原理 自我名言只有努力才能追逐梦想只有努力才不会欺骗自己。 喜欢的点赞收藏关注一下把 文件分为被打开的文件和没被打开的文件前面两篇博文主要讲解的是进程与被打开文件的关系。今天这篇博客讲的是没被打开的文件如何在磁盘上存放文件系统如何管理文件以及软硬连接。 1.理解文件系统 问没有被打开的文件该如何被操作系统管理呢 没有被打开的文件只能在磁盘上静静的放着磁盘上有大量的文件也必须被管理静态管理起来方便我们随时打开。这些工作是由文件系统做的。 在理解文件系统之前我们必须搞懂磁盘上的文件是怎么存的。 我们似乎还没有见过磁盘这里先补充一些磁盘的有关知识。 1.1磁盘的物理结构 我们目前很少看见磁盘了使用最多的就是SSD固定硬盘。 磁盘是我们计算机中唯一的一个机械结构 磁盘是一个机械结构外设所有磁盘访问速度很慢相对于CPU和内存来说。 但是在企业端磁盘依旧是存储主流。磁盘具有造价低存储量大等特点。。。 注意磁头和盘面没有接触 距离就像一架波音747在距离地面一米高速飞行。 为什么这样说呢因为盘片一秒可以上万转。 当盘面高速旋转时磁头会漂浮起来。 磁盘还需要防止抖动。虽然盘面看起来光滑的但是表明是存储数据的地方如果磁盘抖动导致磁头把盘面刮花就会丢失数据就好像以往看碟片出现花纹情况就是出现了数据丢失。 1.2磁盘的存储结构 磁盘的存储是分为那个磁道那个盘面那个扇区的。
问磁盘寻址的时候基本单位是bit还是byte 注意磁盘寻址的时候基本单位既不是bit更不是byte而是一块块扇区。也就是说数据都在扇区放着。 每一块扇区都是512byte。靠近圆心存储密度急远离圆心密度疏。 如果在单面上如何定位一个扇区呢 首先要确定在那个磁道。 其次确定在对应磁盘的哪一个扇区。 那如何确定在那个磁道呢 其实磁头来回摆动的时候就是在确定在哪一个磁道。 如何确定在哪一个扇区 盘面在高速旋转的时候就是让磁头定位扇区。 一个盘片有两个盘面两个盘面都可以存储数据那另一面怎么存储数据 有多少盘面就有多少磁头。并且这些磁头是共进退的。 那如何在磁盘中定位任何一个扇区呢 1.先定位在哪一个磁道/柱面因此磁头是共进退的磁道一旦确认所以磁头就不动了。 2.在定位哪一个磁头也就是确认在哪一个盘面。 3.最后定位在哪一个扇区。 磁道track柱面cylinder磁头head扇区sector。 因此磁盘中定位任何一个扇区采用的硬件级别定位方式CHS定位法 1.3磁盘的逻辑结构 还记得磁带吗卷起来是圆的扯出来是线性结构。 磁盘物理上也是圆形在逻辑上想象成线性结构。 假设这个磁盘只有两个盘片四个盘面三个柱面
我们把整个磁盘从逻辑上看做一个sector arr[n]把对磁盘的管理变成对数组进行管理。 请问现在要找到一个扇区该如何找到呢 这时只需要直到这个扇区的下标就可以定位一个扇区 而在操作系统内部称这种地址为LBA地址逻辑块地址。 假设盘面4磁道/柱面10扇区100扇区大小512byte。 4 * 10 * 100 * 512总容量byte 4 * 10 * 100下标范围 在物理层面上磁盘定位一个扇区采用的是CHS定位法那么操作系统如何将逻辑上LBA地址线性地址转化成CHS对应方案呢 假设下标123 12310000 — 0号盘面 H 1231001 — 1号磁道 C 123%1001 — 1号扇区 S 操作系统以这样的算法将LBA地址转化成磁盘能认识的CHS地址进而访问磁盘的地址。 为什么OS要进行逻辑抽象呢直接用CHS不行吗 1.便于管理是管理一个数组号还是三维立体结构好呢 2.不想让操作系统代码和硬件强耦合如果底层用的是SSD或者其他硬件存呢OS只需把LBA转化成其他的就行了 虽然磁盘的访问基本单位是512byte但是依旧很小想读取4KB内容需要8次IO。知道木桶原理就知道访问速度根据最低来进行的。因此OS内的文件系统定制的进行多个扇区的读取—-1KB2KB4KB为基本单位。所以哪怕只想读取1bit也必须要将4KB加载到内存进行读取或者修改如果有必要再写回磁盘 操作系统的文件系统一般默认以4KB大小也就是8个扇区为基本单位来进行系统和磁盘IO的过程。 内存也是被划分成为4KB大小的空间被OS进行内存管理——页框 磁盘中的文件尤其是可执行文件按照4KB大小划分好的块—–页帧 把文件加载到内存就是把数据放到页框里。 假设磁盘500G我们看如何存储文件的。 假设一个磁盘划分4个盘C/D/E/F盘其实就是把整个磁盘划区。 如果能把100G大小空间管理好直接把办法对其他区复制粘贴整个磁盘就可以管理好。 现在对每个区分组。
如果我把5G大小空间管理好对其他分组进行复制粘贴这100G也能管理好。 具体来看看文件系统是如何对空间进行管理的 1.4文件系统 Boot Block分区的开头是分区表。存放各种分区的情况如OS系统在那个分区图形化界面在那个区等。 Super Block保存的整个文件系统的信息整个分区有多少分组起始块号结束块号是多少等等而且并不是每个分组都有这个Super Block只存在于一个或者多个分组。 那为什么Super Block不放在分区而放在分组呢 这样做是为了备份。万一这个文件系统坏掉了可以把其他分组保存的文件系统的信息拷贝过来这样就完成了文件系统的修复。 文件内容属性 注意Linux的文件属性和文件内容是分批存储的。 文件属性存储在InodeInode是固定大小一个文件一个Inode记录文件的几乎所有属性但文件名并不在Inode中存储 文件内容存储在data blocks中随着应用类型变化大小也在变化。 Inode为了进行区分彼此每一个I弄得都有自己的ID! ls -li //查看Inode编号查找一个文件的时候统一使用的是Inode编号。 先去Inode Bitmap查看这个位置是否被占用再去Inode属性里查找block这个数组数组保存文件内容保存在data blocks那些数据块中 下标0-11直接指向存放数据的数据块。 下标12-14指向的虽然也是一个数据块但是数据块不光可以保存数据也可以保存其他的block id。 这样大型文件也可以存储。 删除文件也是使用Inode 只需要去把Inode Bitmap把该位置1改成0就去把Block Bitmap把该位置变成0就好了。 但是在Linux下我们查找删除文件都用的是文件名而不是Inode啊 问目录是文件吗 Linux一切皆文件因此目录也是文件。 既然是文件就有自己的Inode和date blockInode放的是目录的属性那数据块里放的是什么 其实放的是当前目录下文件名和Inode的映射关系 因此目录下创建和删除文件必须要有写的权限。 如果有一次误删了重要的文件我该怎么做呢 最好什么都不要做如果对其他文件进行了读写Inode会被覆盖。 想恢复文件怎么做呢 我们需要知道文件的Inode去Inode Bitmap把该位置由0变1然后再去Inode找到数据块的映射关系根据映射关系把Block Bitmap对应的位图中由0变1这样文件内容就回来了。 如何知道Inode呢 我们只知道文件名并不知道Inode其实OS也考虑到这点所以OS内包含了一个日志信息当删除一个文件OS会把对应删除的文件与Inode对应关系临时存储在日志中注意这个日志也会有保存时间的。 2.软硬链接 2.1什么是软硬链接 软链接 ln -s myfile.txt soft_file.link硬链接 ln myfile.txt hard_file.link对软硬链接发现了什么
发现软链接有独立的Inode硬链接和被链接的文件具有相同的Inode。 软硬链接的区别是否具有独立的Inode。 软链接具有独立的Inode可以被当作独立的文件看待。 硬链接没有独立的Inode那硬链接该如何理解呢或者建立一个硬链接究竟是做了什么 首先知道建立硬连接根本没有创建文件因为没有给硬链接分配独立的Inode既然没有创建文件那一定没有自己的属性集合和内容集合你用的一定是别人的Inode和内容。
这里就回答了建立硬链接就是在指定路径下新增文件名和inode的映射关系 当删除myfile.txt时只是将该Inode的映射关系减1。但是Inode还在因此还可以通过hard_file.link与Inode的映射关系找到该文件的内容。 那什么时候一个文件算被真正删除呢 当一个文件的硬链接数变成0的的时候这个文件才算真正被删除 软链接有自己独立的Inode和内容当我们删除myfile.txt软链接就出错但是我们知道Inode还在。 由此可见软链接内容保存的不是与文件Inode的映射关系。 其实软链接里面保存的是与文件所处路径的映射关系。 当把文件删除时这个映射关系就出错了。 软链接其实就相当于windows桌面上的快捷方式。 2.2软硬链接的作用 软链接的应用场景相对于快捷方式否则执行一个进程需要找到该进程所在路径才能运行进程而有了软链接直接运行软链接就可以执行当前进程。
unlink soft_file.link //删除链接文件硬链接的应用场景
一个普通文件创建硬链接数为1而创建目录硬链接数为2为什么 一个普通文件本身就有一个文件名和自己Inode的映射关系。因此为1 目录也是一个文件具有独立的Inode首先就有一个映射关系。这是一个硬链接。进入目录之后发现 .当前目录与新建目录lesson1的Inode是一样的。所以当我们执行一个进程的时候通常是./a.out其实就相对于lesson1/a.out. 也是一个文件名.就相对于当前目录lesson1的硬链接因此lesson1的硬链接数为2。 当在lesson1目录下在创建一个empty目录发现硬链接数由2变成3了。 这是因为empty目录下有一个…上层目录这个文件与lesson1的Inode一样相对于又是一个硬链接因此lesson1的硬链接数变成3。
Linux为什么不允许普通用户给目录创建硬链接而可以创建软链接呢 其实.和. .不就是给目录建立的硬链接嘛不过这是由操作系统自己创建的硬链接OS自己弄不怕出错而怕用户创建硬链接出错。 3.动静态库 关于动静态库的知识在前面【Liunx】开发工具第5章节细说了一些内容这里主要是实现动静态库。 静态库.a结尾程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 动态库.so结尾程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。 3.1什么是库 程序在经过预处理编译汇编之后就要链接了链接就是将.o文件和库链接起来形成可执行程序。 下面我们将演示类似与库的思想。 问如果要写一个库需要包含main函数吗 其实并不需要如果库里面已经帮忙写好了那我们在main函数中写的代码有什么用呢 这里创建main函数主要为了演示代码的正确性。 首先建立一些文件写简短的addsub函数的实现。 gcc -c main.c //形成同名的.o文件.o文件是重定位目标二进制文件 现在三个.c文件都已经经过预处理编译汇编变成了.o文件。下面就该链接了。 把所有.o文件链接起来有两种方式 gcc -o mymath main.o my_add.o my_sub.o //直接把.o链接起来gcc -o mymatc main.c my_add.c my_sub.c //先把.c文件形成对于的.o文件再去链接当所有.o文件链接好了就形成了可执行程序。 假如写库的人给不想给用库的人自己的.c文件那就给用库的人提供自己的.o可重定位目标二进制目标文件让用库的人来用自己的代码来进行链接就行了。 在预处理阶段就报错了发现找不到头文件因此我们也把头文件引入。 这样编译就没报错了。 下面将所有.o文件链接起来 结果是对的。证明编译是没问题的。 虽然现在还不懂写库但是未来我可以给对方提供.o文件方法的实现.h文件都有什么方法然后对方就可以编译了。——库的思想。 .h文件好处理上面都是没有经过编译的字符类的有没有它能自己看自己查。 但是如果有一万个.c文件难道要把这一万个.c文件都编译成了.o文件在加上头文件一万个就有两万个文件就全部直接给用库的人那用库的人在写命令行的时候是不是太麻烦了。 因此我们可以尝试将所有的.o文件打包给对方提供一个库文件即可。 库文件就是多个.o文件打包合并成一个文件这个文件就是库然后打包工具和打包方式的不同就有了动态库和静态库。 库的本质就是.o文件的集合。 3.1静态库和静态链接 生成静态库 ar -rc libmymath.a my_add.o my_sub.o ar是gnu归档工具rc表示(replace and create) 将my_add.o和my_sub.o归并到libmymath.a。 交付库库文件.a .so匹配的头文件都给别人 .PHONY:outputoutput:mkdir -p mylib/includemkdir -p mylib/libcp -f *.a mylib/libcp -f .h mylib/include 写好库之后就可以把库发布出去了。 tar czf mylib.tgz mylib //打包然后别人下载安装。 cp mylib.tgz ../test //相当于下载tar xzf mylib.tgz //解压上面就用cp已经tar命令模仿库的下载的过程。但是还没有安装。 安装的本质就是把对应的软件安装到特定的目录下就是把它对应的可执行程序拷贝到指定的系统能够找到的目录。 这里先试试不安装直接用。 这里报找不到头文件的错误但是mylib里面明明就有我的头文件啊。 其实这是因为#includemy_add.h 会在当前路径下找但是由于我的库在mylib目录下也就是说不在当前目录因此需要指明头文件在哪。 gcc -o mymath main.c -I./mylib/include //-I指明头文件报找不到库在哪 gcc -o mymath main.c -I./mylib/include -L./mylib/lib //指明头文件在哪指明库在哪但是还是报同样的错误但这次肯定不是找不到库在哪里了那这事因为什么呢? 这是因为如果要链接第三方的库必须指明库的名称。 但我以前写代码的时候从来没有指明库的名称 gcc —C g —C 编译器默认可以识别CC自带的库。 指明了名称为什么还有问题 原因在于库名称不对 库名称去掉前缀去掉后缀剩下的才是库的名称。 gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath查看可执行程序依赖的动态库列表 ldd mytestfile mytest发现我的库明明是静态库为什么这里是动态链接 gcc默认的是动态链接的建议行为对于一个特定库来说究竟是动态库还是静态库取决于你提供的是动态库还是静态库动态库和静态库都给gcc默认是动态链接。 形成一个执行成程序可能不仅仅依赖一个库。 对于多个库gcc也是一个个进行链接的。 对于执行一个进程需要再命令行写一大推的命令显得太麻烦了。 我们可以把库安装到指定路径下。 ls /usr/include //头文件 ls /lib64 //库文件sudo cp mylib/include/ /usr/include //安装头文件 sudo cp mylib/lib/*.a /lib64 //安装库文件我明明将头文件和库文件安装到指定目录下了为什么还报错这里肯定是是把相应的文件加载到相应的位置。 还记得上面提过使用第三方库要指定库名称。 这里加上库名称就好了。
删除 sudo rm /usr/include/my_ * sudo rm /lib65/libmymath.a3.2动态库和动态链接 生成动态库 shared: 表示生成共享库格式 fPIC产生位置无关码(position independent code) 库名规则libxxx.so 位置无关码等到动态库加载原理细说。 gcc -c -fPIC my_add.c gcc -c -fPIC my_sub.cgcc -shared -o libmymath.so my_add.o my_sub.o这里没有再像静态库那样麻烦再打包什么的而是直接把动态库拷贝过去都是一样的效果。 gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath加载共享库时出错libmymath.so:无法打开共享对象文件没有这样的文件或目录。为什么出现找不到的错误 我不是已经告诉库文件路径和库名称了嘛。 告诉谁了 我其实只是告诉gcc了当把程序编译完和gcc还有关系吗 和gcc没有关系了。 程序运行起来OS和shell也是需要知道库再哪里的而自己库根本没有在系统指定路径下因此OS无法找到。
这里介绍四种解决方法。 3.2.1通过环境变量找到动态库路径 程序在加载进程时除了在默认路径下找也会在LD_LIBRAY_PATH路径下找。 echo \(LD_LIBRARY_PATH //把路径信息打印到显示器把库路径添加到环境变量里。 export LD_LIBRARY_PATH\)LD_LIBRARY_PATH:/home/wdl/linux/test_10_28/mylib/lib然后运行就没问题了。 但是当我重新登录shell时发现又不能运行了。 这是因为我们修改的只是子进程的环境变量当子进程退出在重新登录shell如果不对该子进程的环境变量进行修改它默认用的是父进程的也就是shell的环境变量。 3.2.2把动态库拷贝到默认路径下 sudo cp mylib/include/* /usr/include //安装头文件 sudo cp mylib/lib/*.so /lib64 //安装库文件3.2.3添加到配置文件中 cd /etc/ld.so.conf.d 这些都是系统默认给我们配置好的文件。 sudo touch lib.confsudo vim lib.conf当配置文件写好保存退出 发现还是找不到错误这是因为写完配置文件需要更新一下。 sudo ldconfig这样就没问题了。 如果要删除刚才的配置文件在删除之后也需要sudo ldconfig更新一下。 3.2.4建立软链接 最简单的方法就是建立软链接 ln -s /home/wdl/linux/test_10_28/mylib/lib/libmymath.so libmymath.so在当前目录下给我们的库建立一个软链接然后运行./mymath可以正确运行说明在搜索动态库的时候就能够默认在当前目录下搜索。 如果不想在当前目录下建立软链接就想在系统中可以用它。可以把这个软链接建立到对应的系统路径下。 sudo ln -s /home/wdl/linux/test_10_28/mylib/lib/libmymath.so /lib64/libmymath.so3.3动静态库的加载原理 3.3.1静态库加载原理 其实静态库并不需要加载在编译可执行程序的时候只是把静态库里面的代码拷贝一份给可执行程序需要一份就拷贝一份需要多份就拷贝多份。 那把库代码拷贝到可执行程序的哪里呢 拷贝到代码区。可执行程序文件本身也有逻辑地址静态库在该文件的代码区从0x00000000 到0xffffffff编址。 但是当可执行程序加载到内存中这些重复的代码就造成了内存空间的浪费。 静态库是以绝对编制的方式在该文件的代码区进行编制的。 3.3.2动态库加载原理 静态链接是将静态库的代码通过绝对编制的方式拷贝到可执行程序的代码区。而动态链接是将动态库里指定函数的地址写入到我们的可执行程序中。 这个地址是偏移地址就是相对于libc.so(动态库)的地址。 假设动态链接调用的是printf函数就将printf函数在动态库中的偏移量写入到可执行程序中。 当执行到printf时经过页表读取时发现在可执行程序中这个这个printf代码不存在。 但是在编译的时就在可执行程序表明这是一个外部地址需要访问动态库库。因此OS先暂停执行printf而先将动态库加载到内存然后将库中的内容经过页表映射到进程的共享区。 动态库经过页表映射到共享区立马就决定了这个库的起始地址。 虽然在可执行程序中printf语句只是说我们用了那些库。但是不用担心在链接的时候printf中已经填写好了printf在库的偏移量 因此当想调用printf的时候库一旦完成了加载映射的过程之后。想跳转执行动态库中的方法直接在自己的上下文中跳转。 库加载进来然后就知道了这个库在共享区的地址也是这个库的起始地址这时只要拿着printf在链接时的形成的printf在库中的偏移量再加上这个库的起始地址就找到这个代码在共享区的地址然后去调用这个函数调用结束之后再返回代码处向后继续执行。 这就是动态库访问加载的过程。