Python 踩坑之旅文件系统篇其一文件夹也是个文件
| 代码示例支持 |
|---|
| 平台: 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 这层来看, 因为它:
- 屏蔽下层不同设备厂商数据存储实现
- 抽象并统一了数据存储接口
只要明白了它如何组织文件/文件夹, 基本上就明白了人们常说 everything is a file 的意思.
具体到数据结构上, 要看虚拟文件系统上规定了针对文件系统的4类数据结构:
- superblock
- 用来存储挂载的文件系统的元信息 (比如inode 数目等)
- 简化理解起来就像是文件系统的索引系统, superblock 决定了如下几个数据结构的分布
- inode, 用来存储具体数据的单元 (包括人们通常理解的 file 实体和文件夹)
- dentry, directory entry, 用来描述文件夹信息
- file obj, 进程打开文件描述
对VFS来讲, 无论是存储了具体字节数据的文件, 还是文件夹, 本质都是个 inode 作元信息描述的逻辑结构.
无非文件夹不包括具体数据信息描述, 但包含一些指针 (指向该文件夹包含的一系列数据文件或者子文件夹). 相反, 一个指向数据的 inode 不包含子目录或文件们.
1.3 扩展
基本了解了文件系统的组织方式后, 留几个问题大家给大家做扩展思考?
- 通常我们说一个文件系统满盘了, 可能扩展哪几种满盘?
- 我只创建文件夹但不创建文件, 文件系统会满盘么?
- 文件系统有时候出现错乱, 需要进行 fs check, 这个时候可能是什么坏掉了?
1.4 技术关键字
关键字
- Linux Kernel
- VFS
- Inode / Dentry / Superblock
一些可以参考的资料
- 什么是 superblock, inode, dentry的网友讨论: https://unix.stackexchange.com/questions/4402/what-is-a-superblock-inode-dentry-and-a-file
- Inode structure and Inode table http://140.120.7.21/LinuxKernel/LinuxKernel/node17.html
- Dentry 数据结构介绍和描述 http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch12lev1sec7.html
下期预告
文件系统篇 Umask 到底影响了谁
- 水平有限, 有问题欢迎指正.
- Life is short. We use Python
Python 踩坑之旅文件系统篇其一文件夹也是个文件的更多相关文章
- Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...
- [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...
- Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...
- [代码修订版] Python 踩坑之旅进程篇其五打不开的文件
目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...
- Python踩坑之旅其一杀不死的Shell子进程
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...
- Python踩坑之旅其二裸用os.system的原罪
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 1.5 填坑总结 2. 前坑回顾 2.1 Linux中, 子进程拷贝父进程哪些信息 2.2 Agent常驻进程选择& ...
- 美团热修复Robust的踩坑之旅-使用篇
最近需要在项目中使用热修复框架,在这里以美团的Robust为主写一篇文章总结一下学习的过程. 一直认为要学习一个框架的原理,首先需要让他跑起来,从效果反推回去,这样更容易理解. 一.美团Robust的 ...
- vue+ vue-router + webpack 踩坑之旅
说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案 老司机可以忽略下面的内容了 1)起因 考虑到数据分离的问题 因为server是express搭的 自然少 ...
- 微信小程序之mpvue+iview踩坑之旅
因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...
随机推荐
- Vue-Router中History模式
目录 history路由 官方示例 Express中间件 客户端兜底404 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在 ...
- 【redis】redis应用场景,缓存的各种问题
如果你还不知道redis的基本命令与基本使用方法,请看 [redis]redis基础命令学习集合 缓存 redis还有另外一个重要的应用领域——缓存 引用来自网友的图解释缓存在架构中的位置 默认情况下 ...
- 随笔编号-16 JAVA知识框架
基于 J2EE 列举的知识架构,大体列举开发基础知识.帮助我随时查缺补漏,奉行好记性不如烂笔头.写了这该随笔,以便后续查询. 1 JAVA简介 2 JAVA编程环境 3 JAVA基本编程结构 4 ...
- Redis的初识
简介 已经有了Membercache和各种数据库,Redis为什么会产生?Redis纯粹为应用而产生,它是一个高性能的key-value数据库.Redis的出现,很大程序补偿了Memcached这类k ...
- net core天马行空系列: 泛型仓储和声明式事物实现最优雅的crud操作
系列目录 1.net core天马行空系列:原生DI+AOP实现spring boot注解式编程 哈哈哈哈,大家好,我就是那个高产似母猪的三合,长久以来,我一直在思考,如何才能实现高效而简洁的仓储模式 ...
- JavaWeb实现增删查改(图书信息管理)——之查询
关于此次CRUD所需要的jar包,本人把文件放在了百度网盘,需要的自行去下载: 链接:https://pan.baidu.com/s/1Pqe88u6aPaeVjjOq1YFQ-w 提取码:pim ...
- 【Edu 67】 补题记录
CF1187D. Subarray Sorting 想要把一个数x换到前面,x一定是小一点的值.由于B串是固定的,A串可调整,我们可以遍历B数组,对于B[i],找到对于在A数组的位子pos,判断1-p ...
- 分层图 单调决策性DP
easy 写法. #include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt" ...
- POJ-2018 Best Cow Fences 二分
题意:找到一个连续区间,区间的长度至少大于f,现在要求这个区间的平均值最大. 题解: 二分找答案. 每次对于2分的mid值, 都把原来的区间减去mid, 然后找到一长度至少为f的区间, 他们的区间和& ...
- codeforces 233 C. Cycles(贪心+思维)
题目链接:http://codeforces.com/contest/233/problem/C 题意:在一个无相图中有N个长度为3 的回路,输出符合条件的图.注意此图的节点数不得超过100 题解:贪 ...