文章目录
磁盘计算机上唯一的一个机械设备,同时它还是外设
机械磁盘很便宜,虽然效率会慢一些,所以企业一般使用机械磁盘,因为便宜
磁盘不仅仅外设,还是一个机械设备(盘片、磁头),所以磁盘一定非常慢
盘片:一片两面,有一摞盘片
磁头:一面一个磁头
一个磁头负责一面的读取
马达比如说剃须刀,或者手机的震动等
所以盘片就可以 以顺时针的方式高速旋转
同时在磁头位置也存在一个马达,控制磁头左右来回摆动
磁头是共进退的,要不一块过去,要不就一块不去
磁盘盘片上有无数个基本单元,每一个基本单元按照特定的空间排布好的,每一个单元就是磁铁
南极表示1,北极表示0,
向磁盘写入:把北极改成南极 (N->S)对内容做磁化
删除磁盘数据:把数据从南极设置为北极 (S->N)
这样就可以完成微观上 一个比特位的读和写
磁头本质上 是对数据做写入和读取,更改基本元素的南北极,读取南北极
整体结构
抽象的一面结构
磁盘中存储的基本单元是扇区,一般扇区的大小为512字节或者4KB字节
一般磁盘所有的扇区都是512字节大小
同半径的所有的扇区即为磁道
1.先定位在哪一个磁道—由半径决定
2.再确定在该磁道,在哪一个扇区,根据扇区的编号,来定位一个扇区
所以首先要定位哪一个面
磁头是共进退的,半径相同的每一个面上的磁道共同在抽象上就会形成一个柱面
只需要确定用哪一个磁头读取,磁头的编号就表示哪一个面
所以定位任意一个扇区,需要确定 磁头head 、柱面 cylinder、扇区 sector 即CHS定位法
普通文件中包含属性和数据,都可以看做数据(0,1),占用一个或者多个扇区,来进行自己的数据存储
既然能用CHS定位为任意一个扇区,就能定位任意多个扇区,从而将文件从硬件角度进行读取或者写入
OS内部是不是直接使用CHS地址?不是
第一点:因为OS是软件,磁盘是硬件,硬件定位一个地址,用的是CHS,但是如果OS直接用了这个地址,万一硬件改变,OS也要发生变化,所以OS要和硬件做好解耦工作
第二点:即便是扇区512字节,单位IO的基本数据量也是很小的,所以硬件是按照512字节处理,
操作系统实际进行IO,基本单位是4KB
操作系统和磁盘进行交互时,基本以4KB为单位,
基本大小:进行磁盘读取和磁盘写入时,必须以基本单位为基本大小,来与外设进行交互
哪怕只修改一个比特位,也要把一个比特位所在的4KB全部读到内存,
把一个比特位改完,再把4KB内容全部写到目标文件中,要以块的方式整体与外设进行交互
所以一般把磁盘称为 块设备
所以OS需要有一套新的地址,来进行块级别的访问
把盘面抽象成一种线性结构
以一个盘面举例
相同磁道的东西一定放在一起的
整体可以看作是数组,设置数组名为 sector_disk1
初步完成了从物理逻辑到线性逻辑抽象的过程
因为看作是一个数组,而数组都是有下标的
假设数组下标为n,定位一个扇区,只需要数组下标就可以定位一个扇区了
OS是以4KB为单位进行IO的,一个操作系统对应的文件块要包括8个扇区
计算机常规访问方式:采用起始地址+偏移量的方式
只需要知道数据块起始位置的地址,即第一个扇区的下标地址 + 4KB(块的类型)
可以把数据块看作一种类型
所以块的地址本质就是数组的一个下标N
N的地址在OS中被叫做LBA,即逻辑块地址
假设LBA地址为6500 ,单片大小为5000
首先确定在那一面,也就相当于在哪一个磁头上
H(磁头): int n=6500/5000=1 说明H的地址在第2面上
C(柱面):6500/1000=6 1000为磁道的大小,对应的H就在6号磁道上
S(扇区): 6500 %1000=500
所求扇区 就在 2号面中的6号磁道的第500个扇区
连续读取8个扇区,就能得到块
为了方便管理,就把数组拆分为一个个的区域
若感觉管理500GB太难了,就减少管理,从而管理150GB,将管理小的经验复制,从而使每一个小的都管理好
从而使500GB整体管理好 ,这种思想就叫做分区
虽然分完区小了很多,但依旧很大,所以操作系统对整个分区还会在做分组
假设每个区为150GB,就把15GB为一组,把其中一个组管理好了,按照一个组的管理方式就把所有组管理好了
由于每个区都可以分组,就有了 Block group
一个分区当中最开始有一个Boot Block
会保存与操作系统启动相关的内容,如分区表和操作系统镜像地址
一个组中分为 Super Block(超级块) 、Group Descriptor Table(组描述符)、Block Bitmap、inode Bitmap(位图)、inode Table (inode表)、Data blocks(数据块)
Super Block 保存的是文件系统的所有属性信息 如文件系统的类型、整个分组的情况
Super Block在各个分组里面可能都会存在,而且是统一更新的
为了防止Super Block区域坏掉,如果出现故障,整个分区不可以被使用,所以要做好备份
Group Descriptor Table
GDT:组描述符 – 改组内的详细统计等属性信息,用来描述整个
一般而言,一个文件内部所有属性的集合,被称为inode节点 ,大小一般为128字节
一个文件,一个inode,一个分区内部也会存在大量的文件即会存在大量的inode节点,一个group,需要有一个区域专门保存该group的所有文件的inode节点 即 inode table -----inode表
文件的内容是变化的,用数据块对文件内容保存的,所以一个有效文件要保存内容就需要1/n数据块
若有多个文件就需要更多的数据块,数据块称为 Data blocks
linux查找一个文件,是要根据inode编号,来进行文件查找到,包括读取内容
一个inode对应一个文件,而该文件inode属性和该文件的数据块是由映射关系的
inode Bitmap
共有4096*8个比特位,按照从低向高扫描位图时,比特位的位置对应inode表中的inode
为1表示inode正常工作,为0表示inode不正常工作
每一个比特位表示 一个inode是否空闲可用
Block Bitmap
每一个bit位表示data block是否空闲可用
1.inode与文件名
Linux系统只认inode编号,文件的inode属性中,并不存在文件名
文件名是给用户用的
2.目录是文件么?
是的,目录有inode和内容
3.任何一个文件,一定在目录内部,所以目录的内容是什么?
目录要有内容就需要数据块,目录的数据块里面保存的是该目录下 文件名和inode编号对应的映射关系
在目录内,文件名和inode编号互为key值
4.当我们访问一个文件的时候,是在特定目录下访问的 cat log.txt
1.先要在当前目录下,找到log.txt 的 inode编号
2.一个目录也是一个文件,也一定属于 一个分区,在该分区中找到分组,在该分组中对应的inode table中,找到文件的inode
3. 通过inode与 对应的data block的映射关系,找到该文件的数据块 ,并加载到OS,并完成到显示器
创建文件myfile.tx,并向文件中一直追加 hello world
[yzq@VM-8-8-centos lesson1]$ touch myfile.txt
[yzq@VM-8-8-centos lesson1]$ echo "hello world" >> myfile.txt
[yzq@VM-8-8-centos lesson1]$ echo "hello world" >> myfile.txt
[yzq@VM-8-8-centos lesson1]$ echo "hello world" >> myfile.txt
[yzq@VM-8-8-centos lesson1]$ echo "hello world" >> myfile.txt
[yzq@VM-8-8-centos lesson1]$ ls -li
total 4
1311370 -rw-rw-r-- 1 yzq yzq 48 Apr 2 22:25 myfile.txt
查询当前myfile.txt文件的 inode编号为1311370
建立软链接 ln -s
[yzq@VM-8-8-centos lesson1]$ ln -s myfile.txt my-soft
[yzq@VM-8-8-centos lesson1]$ ll
total 4
-rw-rw-r-- 1 yzq yzq 48 Apr 2 22:25 myfile.txt
lrwxrwxrwx 1 yzq yzq 10 Apr 2 22:30 my-soft -> myfile.txt
对myfile.txt文件进行软链接,并命名为my-soft
当前文件链接数为1,并以l开头说明
[yzq@VM-8-8-centos lesson1]$ ls -li
total 4
1311370 -rw-rw-r-- 1 yzq yzq 48 Apr 2 22:25 myfile.txt
1311371 lrwxrwxrwx 1 yzq yzq 10 Apr 2 22:30 my-soft -> myfile.txt
输入 ls - i, 发现两者的inode编号不同
说明软链接是一个独立的链接文件,有自己的inode编号,必有自己的inode属性和内容
软链接内部放的是自己所指向的文件的路径
可以认为保存的是一个字符串,保存的是当前myfile文件的路径
建立硬链接 ln
[yzq@VM-8-8-centos lesson1]$ ln myfile.txt my-hard
[yzq@VM-8-8-centos lesson1]$ ll
total 8
-rw-rw-r-- 2 yzq yzq 48 Apr 2 22:25 myfile.txt
-rw-rw-r-- 2 yzq yzq 48 Apr 2 22: my-hard
lrwxrwxrwx 1 yzq yzq 10 Apr 2 22:30 my-soft -> myfile.txt
对myfile.txt文件进行硬链接,并命名为my-hard
发现 myfile.txt文件的链接数变为2
[yzq@VM-8-8-centos lesson1]$ ls -li
total 8
1311370 -rw-rw-r-- 2 yzq yzq 48 Apr 2 22:25 myfile.txt
1311370 -rw-rw-r-- 2 yzq yzq 48 Apr 2 22:25 my-hard
输入 ls-li 后,发现硬链接my-hard和myfile.txt文件的inode编号相同
硬链接和目标文件公用同一个inode编号,意味着一定是和目标文件使用同一个inode
硬链接没有独立的inode
硬链接建立了新的文件名和老的inode的映射关系
若此时将myfile.txt文件删除,就会发现my-hard依旧可以运行 ,并为之前myfile.txt文件的内容
[yzq@VM-8-8-centos lesson1]$ rm myfile.txt
[yzq@VM-8-8-centos lesson1]$ ll
total 4
-rw-rw-r-- 1 yzq yzq 48 Apr 2 22:25 my-hard
[yzq@VM-8-8-centos lesson1]$ cat my-hard
hello world
hello world
hello world
hello world
ref count默认为1 ,若有新的指向过来,执行++ 变为2
ref count称为 硬链接数 本质是一种引用计数
代表有多少个文件名指向我,默认情况下有一个文件名和inode映射关系就为1,若再建立一个文件名和inode的映射关系就增加为2,若删除一个文件,则ref count-- ,直到计数为0对应的文件才真的会删掉
若可执行程序在多级目录中,正常来说想要调用多级目录只能一层一层就写

通过使用软链接,将需要调用的可执行程序命名为mytest
此时直接调用mytest 即可达到调用多级目录下的可执行程序的目的

创建多个文件 ,硬链接数都为1

创建一个目录 dir ,硬链接数为2

进入目录dir中,. 作为隐藏文件 inode编号与目录dir相同,所以硬链接数为2
. 与 dir 目录的inode编号相同
… 与上一级目录的inode编号相同
在dir目录下再次创建一个子目录d1
d1中的. 的inode编号与d1目录相同
d1中…与上一级目录dir的inode编号相同
dir目录的硬链接数变为 3 ,
除了dir目录本身与目录中的 . 以外 ,在子目录d1下的 … inode编号也与dir目录相同
当给目录dir建立硬链接时,发现并不能成功
若给目录建立硬链接,容易造成环路路径问题
若在lesson1目录找一个文件,依次向下到达dir-link ,而dir-link又相当于是lesson1,所以又会重新在lesson1目录找文件
Access 最后访问时间
Modify 文件内容最后修改时间
Change 属性最后修改时间

change代表对一个文件的属性做修改

chmod+x 对myfile.txt文件的属性做修改,此时change的时间更新成为最新了
modify 代表对文件的内容做修改

使用重定向 往myfile.txt文件中追加内容 ,此时modify的时间更新为最新了,而一般改内容 属性也会跟着变化
Access 文件的访问时间

使用vim通过进入文件中,但不修改 ,而再次使用stat时,Access的时间更新为最新了
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只