代码示例支持
平台: 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. Docker进阶-资源管理Swarm+Portainer

    Docker Swarm资源管理 Docker Swarm是Docker官方三剑客项目之一,提供Docker容器集群服务,是Docker官方对容器云生态进行支持的核心方案. 使用它,用户可以将多个Do ...

  2. (四十二)c#Winform自定义控件-进度条扩展

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  3. 史上最全面的SignalR系列教程-6、SignalR 实现聊天室

    1.概述 通过前面几篇文章对SignalR的详细介绍.我们知道Asp.net SignalR是微软为实现实时通信的一个类库.一般情况下,SignalR会使用JavaScript的长轮询(long po ...

  4. Python笔记_基础

    1.注释 # 单行注释 """ 多行注释,一般用于类说明 """ 或 ''' 多行注释 ''' 2.工作日志 # TODO 说明性文字 记录 ...

  5. 2019年7-8月Leetcode每日训练日志

    2019-08-29 #274 H指数 2019-08-28 #287 寻找重复数 #875 爱吃香蕉的珂珂 #704 二分查找 2019-08-27 #744 寻找比目标字母大的最小字母 #225 ...

  6. [转]Linux系统结构

    Linux系统一般有4个主要部分:内核.shell.文件系统.应用程序. 内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统. 1.linux内核 内 ...

  7. NLP(十四) 情感分析

    情感在自然语言中的表达方式 例句 解释 I am very happy 开心的情感 She is so :( 表达悲伤的图标 import nltk import nltk.sentiment.sen ...

  8. codeforces 876 D. Sorting the Coins(线段树(不用线段树写也行线段树写比较装逼))

    题目链接:http://codeforces.com/contest/876/problem/D 题解:一道简单的类似模拟的题目.其实就是看右边连出来有多少连续不需要换的假设位置为pos只要找pos- ...

  9. “玲珑杯”ACM比赛 Round #18 1147 - 最后你还是AK了(思维,边的贡献)

    题目链接:http://www.ifrog.cc/acm/problem/1147 题解:这题很容易想到的是边的贡献也就是每条边最多被取到几次,和点的贡献类似,那些加边只要加在边贡献大的边上就行.然后 ...

  10. hdu 1540 Tunnel Warfare(线段树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1540 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. ...