1. 程式人生 > >Python 踩坑之旅檔案系統篇其一資料夾也是個檔案

Python 踩坑之旅檔案系統篇其一資料夾也是個檔案

目錄

  • 1.1 案例
  • 1.2 分析
  • 1.3 擴充套件
  • 1.4 技術關鍵字
  • 下期預告
程式碼示例支援
平臺: 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

一些可以參考的資料

  • 什麼是 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