注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

落叶清风L的博客

努力向前

 
 
 

日志

 
 
 
 

Linux文件知识简单总结  

2015-03-24 23:05:25|  分类: linux基础 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
  1. 关于使用open O_CREATE配合O_EXCL 判断文件是否存在引发的问题 :

当文件存在时 , open 函数会返回出错 , errno 值被置为 EEXIST , 此时, 我们的if条件判断出错 , 执行我们的错误处理 . 情况看起来没什么不对的.

于是我们写出了这样的代码:

if ( -1 == open (“test.txt” , O_CREAT|O_EXCL)) {

perror (“open error !”) ;

exit (1) ;

}

其实可以用access 来检测文件是否存在和当前用户身份是否有相应的权限操作这个文件.

这样写 ? 很明显的错误是, 当文件不存在时 , 怎么办 ? 没有传第三个参数啊!!! 函数会怎么处理? 在栈里随便找一个值, 当作权限, 给文件了 , 所以会发现有些奇怪权限的文件. 妹的 , test.txt不存在时 , 每次创建还有可能不一样. 加上第三个参数就好了 .

  1.  三个同步函数 : sync , fsync , fdatasync

由于delay write 的存在 , 内核为了高效I/O 将数据复制到内核缓冲 , 磁盘I/O , 通过缓冲进行. 当有新的内容要占据缓冲时 , 将原来缓冲中的内容输入磁盘.这三个函数就是为了保证磁盘文件系统与缓冲区中内容一致.

sync 之将缓冲内容排入队列 , 并不等待实际内容写到磁盘上和文件相关属性更新.

fsync 等待文件实际内容写入磁盘并修改文件相关属性完毕(如果需要修改),才返回.

fdatasync 等待文件的实际内容写入磁盘后返回 , 不等带文件属性改变修改完毕.

      3.lseek 对于lseek 函数来说,可以使用文件描述符来移动当前文件的偏移量, 超过文件的最长限度,则产生文件空洞,文件空洞是逻辑上的概念.自己试了一下, 妹的,文件系统如何实现的不知道,总之空洞还是要占一定的物理块的, 但是大小比空洞小很多. 可以用ls -sl du -sh 查看对应有空洞文件的大小, du ls -s 均可以查看对应实际占用的物理块的大小.

Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客

可以看到test.txt 是一个有空洞的文件 , 由于实际的物理块只有12K 但是我们看到文件有20480006个字节,bc算一下 , 20000KB左右,显然是比对应的块大小要大很多 . 看看文件里面都是什么吧.


Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客

很多的0 , 用来填充我们的空洞对应的位置. 大部分的东西都是0 . 但当我们在用cat read ,读到的空洞均被视为实际的0 , 而不是跳过空洞.我们使用cat 测试这个现象


Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客
 

        可以看到对应新生成的文件的大小比最初的文件大了很多 , 计算一下实际的物理块大小,20000还要大一些, 这是由于文件使用了若干的块来保存指向实际块的指针. (妹的, 这牵扯到文件结构的问题了.)这个没有验证, 不过也折腾了一天左右 , 最终得到的效果是, 对于一般的文件,是会出现上述情况的 , 但是对于特殊的文件 , 比如内容十分神似的文件 , 或者就压根内容一样(e.g 全都是'a' 或者 其它) 这样的文件妹的再大(只试到百兆) , 似乎不给面子.该多大还是多大, 丝毫不需要额外给块. 好了 , 那只是一个特殊的情况大部分文件是无规则的字符吧.

        4. 关于I /O 的效率 , APUE给出的统计数据显示:缓冲区的大小的选取与磁盘的块长度直接相关.st_blksize的值的大小.(注意区分st_blksize st_blocks , 前者是磁盘的块长度 ,后者是实际的分配512/1024字节块的块数 .至于是512还是1024 , APUE给的说法是是否设置了环境变量POSIXLY_CORRECT若设置了, du 返回的是1024 字节块的块数.

        5. 在调用pread , pwrite , 无法中断定位和读操作. 而且不更新当前文件偏移.也就是说, 读完之后 , 原来文件偏移指针指哪 , 还是哪 , 不变. 这就很吊了 !

      6. 当我们尝试用dup2复制一个描述符时 , 当目标描述符为0 , 1 , 2 , dup2不会关闭对应的描述符 , 毕竟人家是需要常开的 , 每个程序都可能用到 ! 所以 , 还是不要尝试关掉那个 . 有程序会维护这3个描述符 , 至于是谁, 猜猜可能是内核吧. (好多东西,内核帮助我们维护).

        7. 关于文件系统的东西神啊 , 确实好多 , 自己也只是管中窥豹 , 只见一斑 .文件系统的inode三级索引 , 分区信息好多啊 . 就不在此丢银了附图如下 :

Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客

Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客

        从图中可以很清楚的看到通过i节点信息索引到数据的实际块 , i节点中保存的信息又可以有inode信息 , 对应一级,二级,三级索引~ .i节点中还包含了文件的属性信息 (包括文件的权限 , 大小 , 文件的重要的时间信息(a (last access), m (last modify), c(last change) ) .

         还很明显 的看到,目录信息的索引也是通过inode , 索引到物理块,找到对应目录信息.

         还看到了, 硬链接是怎么实现的 , 第二张图显示了 , 为一个文件建立硬链接 将文件所在的原来目录的目录项信息同样的给目标目录中写一份 , 这样 , 目标目录就有了文件的一份信息 . 所以删除文件的函数 unlink 就可以了 , 让文件的引用计数减一 , 当文件的引用计数为0 , vfs 就为我们删调了文件 , 链接数在stat结构中的st_nlink, 回收了inode , unlink 还有一个用途就是创建一个临时的文件.在程序运行之后创建一个文件之后立即调用unlink函数, 这样就保证了当程序非正常结束的时候也可以不遗留下创建的临时文件.相应的link函数是创建一个硬链接的. 而且需要注意的是 , link函数必须是原子的 .

         即在写目录项和修改引用计数必须不可打断地完成 . 否则就会有问题 (很好想吧) . 需要记住的是, 硬链接只能在同一个文件系统中 , 原因是 , 一个文件系统的开头会有sup erblockinode bitmap记录inode信息 , 不同的文件系统, inode信息可以是独立的.(目录项中会保存文件名和文件的inode节点号 , stat函数也可以获得 , 但是具体是怎么找到文件的inode. 没有研究过(VFS的事) . (但既然目录项里有记录,那么找到文件所在目录就可以找到文件的inode , 有了inode 就可以判断对文件是否有相关权限, 然后就可以操作文件了.只可惜的是 ,这只是猜想)等待大神前来解救.

        所以mv的话, 移动文件 , 我们只需要在新的目录项里加上对应要mv 的文件的信息 , 就可以将文件移动到目标目录了 , 再删除旧目录项的记录, OK . Mv 就是这样滴. 关于i节点的信息和inode 索引 , 下面的图来说话吧 .


Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客

超级块:

1.记录blockinode总量

2.记录已使用和未使用的inode/block 数量.

3. blockinode 大小(block 1k ,2k ,4k , inode 128bytes)

4. 文件系统的挂载时间,最近一次写入数据时间,最近一次检验磁盘时间的文件系统 的相关信息.

5. validbit 数值, 表示此分区是否已被挂载.0 表示未被.

文件系统描述符:

描述每个block group 的开始与结束的block号码,以及说明每个区段分别介于哪一 block号码之间.

块对照表:

1. block bitmap 当中可以知道哪些block是空的, 因此可以快速找到空间来处置文 .

2. 当文件删除的时候, 就要对相应的block进行回收.block号码的标志修改为 未使用中.

inode对照表:

与块对照表的功能相仿.

Inode table :

记录文件所有状态信息.包括访问权限信息 , 所属用户,所属组 , a , m , c , file size , 是否设置用户ID , 或设置组ID , 文件创建时间. 该文件内容的真正指向.

Data block:

data block 是用来放置文件实际内容的地方. Data block 大小有1KB , 2KB , 4KB 在格式化的时候就是固定的.

        文件内容是怎么索引的呢? 当然是先找的文件的inode , inode 怎么找到的呢? 通过文件名(具体怎么找到,又回到前面的问题了, 应该是查找目录树, 找到包含此文件的目录项 , 取出文件inode . inode里面存了绝对的信息,包括指向文件内容的块编号.通过块编号就可以找到文件真实内容喽.看看是怎么索引的吧.

Linux文件知识简单总结 - 萧然AND落叶清风L - 落叶清风L的博客

        直接索引的话, 显然不能索引很大的文件 , 一个块大小也就4KB, 要索引1G文件,那得多少直接索引?一个inode显然不够, 所以有了间接索引,双间接索引,三间接 .

          间接索引的意思是,先索引到一个块,这个块里面不是记录的文件实际内容,而是记录块编号,一个编号用一个int,那么假设一个块是4096字节, 就可以再索引到1024个块,加起来就是1024*4k =4M, 双间接类似, 就更大了.1024*1024*4K = 4096M


                                                                                                                                          ------ windleaves

参考书籍 《APUE》 《鸟哥的Linux私房菜》

  评论这张
 
阅读(31)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018