代码示例支持
平台: Mac OS
Python: 2.7.10
代码示例:
- wx: 菜单 - Python踩坑指南代码示例
- github 见code_demo

1.1 案例

这期案例讲的是Unix-Like系统中, 常听到的一句话: 目录也是个文件 或者 everything is a file.

刚接触 Linux 文件系统的同学有时候听到这个很懵, 目录怎么是个文件呢?目录不应该是内部包含文件的载体么?

1.2 分析

分析主要从2个方面展开:

  • ls 实际是使用大量文件系统标准接口实现的结果, 是处理过后的用户程序
  • 从文件系统的组织结构来看穿数据存储和读写方式

如果大家已习惯了 Linux 系统中 ls 命令 (有时候由于alias 存在, 实际是ls --color), 容易产生一种错觉:文件夹和文件这不是天然的被区分为不同的类别了吗?

  • 比如蓝色的文件夹?
  • 黑色的文件?`

实际不是这样子的, ls mkdir touch 一类的文件系统操作命令其实是通过调用文件系统接口实现的用户态程序, 你自己利用python也可以实现一个一摸一样的.

我们来看一些使用 python 访问文件系统的简单例子:

from __future__ import print_function
import os # 简单文件写
with open('./test', 'w+') as fhandle:
fhandle.write('test\n') # 创建文件夹 dirname = os.path.abspath('./test_dir')
if not os.path.exists(dirname):
os.makedirs(dirname) for ind in range(0, 10):
with open('{0}/test_file_{1}'.format(dirname, ind), 'w+') as fhandle:
fhandle.write('1')
dname = '{0}/test_dir_{1}'.format(dirname, ind)
if not os.path.exists(dname):
os.mkdir(dname) # 读文件夹
for obj in os.listdir(dirname):
objpath = os.path.join(dirname, obj)
if os.path.isfile(objpath):
print('{0} is a file'.format(objpath))
elif os.path.isdir(objpath):
print('{0} is a dir'.format(objpath))

因此, 大家理解 ls 类耳熟能详的 Linux 命令是经过代码实现的用户程序, 如果你想且有时间完成可以实现一个 python 版 的ls


更进一步的说, 对文件或者文件夹的操作本质上是用户层的代码实现调用了系统相关的接口. 这代表着文件夹和文件对系统来讲, 就是数据组织上的不同 (数据结构的不同). 那数据或者文件数目是怎么进行组织的?

想了解这个问题就要先了解 Linux 系统上的文件存储层次, 以在 Linux 上挂载的文件系统进程读写为例:

  • 最上层, 用户的程序进程 Process, 通过调用类似open write close 等通用系统函数读写所在挂载目录的文件

  • 中间 Kernel VFS (Virtual Filesystem, 虚拟文件系统)

    • 市面上主流的文件系统并不少, 为了让上层应用不关心如何读写这些内部实现各异的文件系统, Kernel 实现了虚拟文件系统
    • 虚拟文件系统包含一系列的标准;
      • 为了方便理解, 可以简化理解为提供了一系列读写接口标准
      • 上层用户应用使用下层的文件系统不需要关心你是哪个文件系统, 我只要挂载好你到我的系统就能使用标准接口读写
  • 底层, Kernel 内核, 各个设备厂家不同的VFS实现嵌入 kernel 中以支持具体的读写等操作

  • 物理介质层 (块设备等), 真正的硬件设备层

而我们要聚焦到 VFS 这层来看, 因为它:

  1. 屏蔽下层不同设备厂商数据存储实现
  2. 抽象并统一了数据存储接口

只要明白了它如何组织文件/文件夹, 基本上就明白了人们常说 everything is a file 的意思.

具体到数据结构上, 要看虚拟文件系统上规定了针对文件系统的4类数据结构:

  • superblock

    • 用来存储挂载的文件系统的元信息 (比如inode 数目等)
    • 简化理解起来就像是文件系统的索引系统, superblock 决定了如下几个数据结构的分布
  • inode, 用来存储具体数据的单元 (包括人们通常理解的 file 实体和文件夹)
  • dentry, directory entry, 用来描述文件夹信息
  • file obj, 进程打开文件描述

对VFS来讲, 无论是存储了具体字节数据的文件, 还是文件夹, 本质都是个 inode 作元信息描述的逻辑结构.

无非文件夹不包括具体数据信息描述, 但包含一些指针 (指向该文件夹包含的一系列数据文件或者子文件夹). 相反, 一个指向数据的 inode 不包含子目录或文件们.

1.3 扩展

基本了解了文件系统的组织方式后, 留几个问题大家给大家做扩展思考?

  1. 通常我们说一个文件系统满盘了, 可能扩展哪几种满盘?
  2. 我只创建文件夹但不创建文件, 文件系统会满盘么?
  3. 文件系统有时候出现错乱, 需要进行 fs check, 这个时候可能是什么坏掉了?

1.4 技术关键字

关键字

  1. Linux Kernel
  2. VFS
  3. Inode / Dentry / Superblock

一些可以参考的资料

下期预告

文件系统篇 Umask 到底影响了谁


  • 水平有限, 有问题欢迎指正.
  • Life is short. We use Python

Python 踩坑之旅文件系统篇其一文件夹也是个文件的更多相关文章

  1. Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...

  2. [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...

  3. Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...

  4. [代码修订版] Python 踩坑之旅进程篇其五打不开的文件

    目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...

  5. Python踩坑之旅其一杀不死的Shell子进程

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...

  6. Python踩坑之旅其二裸用os.system的原罪

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 1.5 填坑总结 2. 前坑回顾 2.1 Linux中, 子进程拷贝父进程哪些信息 2.2 Agent常驻进程选择& ...

  7. 美团热修复Robust的踩坑之旅-使用篇

    最近需要在项目中使用热修复框架,在这里以美团的Robust为主写一篇文章总结一下学习的过程. 一直认为要学习一个框架的原理,首先需要让他跑起来,从效果反推回去,这样更容易理解. 一.美团Robust的 ...

  8. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

  9. 微信小程序之mpvue+iview踩坑之旅

    因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...

随机推荐

  1. Spring Cloud Gateway 服务网关快速上手

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 ...

  2. (转载)分享常用的GoLang包工具

    分享常用的GoLang包工具 包名 链接地址 备注 Machinery异步队列 https://github.com/RichardKnop/machinery Mqtt通信 github.com/e ...

  3. 由于Microsoft\VisualStudio\14.0\Designer\ShadowCache导致的一个异常问题

    本文引用了一个DynamicDataDisplay和DynamicControl两个类库,本来使用的时候都时正常的,愉快的运行着. DynamicDataDisplay:这是一个用于动态数据可视化的W ...

  4. ASP.NET Core on K8S深入学习(7)Dashboard知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 在第二篇<部署过程解析与Dashboard>中介绍了如何部署Das ...

  5. 终于找到可以一文多发的平台了! openwrite.cn

    openwrite.cn 一文多发平台 有时候自己辛苦写了几个小时的技术文章,被爬虫抓走.自己去全平台一个一个发,又过于麻烦.而且每个平台都不一样,发文同步很困难.那么终于有了一款一文多发的利器:Op ...

  6. shiro@RequiresPermission的设置

    public class MyShiroRealm extends AuthorizingRealm { //slf4j记录日志,可以不使用 private Logger logger = Logge ...

  7. 「每日五分钟,玩转JVM」:线程共享区

    前言 上一篇中,我们了解了JVM中的线程独占区,这节课我们就来了解一下JVM中的线程共享区,JVM中的线程共享区是跟随JVM启动时一起创建的,包括堆(Heap)和方法区()两部分,而线程独占区的程序计 ...

  8. Flink的Job启动JobManager端(源码分析)

    通过前面的文章了解到 Driver将用户代码转换成streamGraph再转换成Jobgraph后向Jobmanager端提交 JobManager启动以后会在Dispatcher.java起来RPC ...

  9. 学会spss就能找到数据分析工作吗

     大学课堂上学习了spss,老师也讲了很多知识,但是现在准备毕业了,我做的实习工作就是用业内的数据进行最新的行业研究.现在真正需要用到spss进行分析了,我却看不懂老板给的数据和分析要求,难道这就是理 ...

  10. Python数据类型详解——元组

    Python数据类型详解--元组 有时候我们的列表数据不想被别人修改时该怎么办? 此时,就可以使用元组来存放,元祖又称为只读列表,不能修改 定义方式:与列表类似,将列表的[]换成()即可. 特性: 1 ...