文件管理


title: 文件管理
date: 2018-05-10 16:59:37
tags: [OS, python]
categories: 操作系统


目标:

通过python模拟终端下的创建/删除文件/文件夹、显示该路径下内容、切换路径、tree等命令。

该代码模拟的是Unix下的superblock和inode进行外存的分配与回收。


文件2.JPG
inode至少包含如下信息:
  • inode 编号
  • 用来识别文件类型,以及用于 stat C 函数的模式信息
  • 文件的链接数目
  • 属主的 UID
  • 属主的组 ID (GID)
  • 文件的大小
  • 文件所使用的磁盘块的实际数目
  • 最近一次修改的时间
  • 最近一次访问的时间
  • 最近一次更改的时间
代码细节:
  • 包含的命令:
    • ls: 显示当前目录下的所有文件
    • mkdir a: 创建名称为a的目录
    • mk a 1000: 创建名称为a的、大小为1000字节的文件
    • tree: 以树的形式显示当前目录下的文件及目录(对不齐)
    • rm a: 移除名称为a的文件/目录(若目录下不为空则无法删除)
  • 代码中inode包含三个直接索引,一级索引,二级索引和三级索引。
import math
import time
# block = []  # 1已用,-1未用
inode_table = []
# root = []
now = []  # 当前路径
# File = {}  # key是文件名,value是inode编号,就是inode_table里的索引位置


class INode(object):  # 每个文件只有一个inode
    def __init__(self, type):
        self.id = -1  # table中的index
        self.type = type  # 文件是0,目录是1
        self.blo = []
        self.time = -1
        self.size = 0
        self.file = {}


class SuperBlock(object):
    def __init__(self):
        self.table = []  # 存block中空的下标
        self.unused_inode = -1
        self.unused_block = -1
        self.used_inode = 0
        self.used_block = 0

    def initial(self, num):  # 初始化table
        sup_tab = self.table
        self.unused_inode = num
        self.unused_block = num
        for i in range(int(math.ceil(num / 10))):
            sup_tab.append(10)
            sup_tab.append([10 * i + j for j in range(9)])
            sup_tab[-1].append([])
            sup_tab = sup_tab[-1][-1]


# 左孩子是该路径节点下的文件,右孩子是该结点的同级文件
class Tree(object):
    def __init__(self, date, num, left=None, right=None):
        self.inode_num = num
        self.parent = None
        self.date = date
        self.left = left
        self.right = right
        self.level = 0

def depth(t):
    if t is not None:
        lDepth = depth(t.left)
        rDepth = depth(t.right)
        return max(lDepth, rDepth) + 1
    else:
        return 0


def preorder(t):
    if t is None:
        return
    else:
        print((t.level)*'   '+'|', end='')
        print('---', t.date)
        preorder(t.left)
        preorder(t.right)


def distribute_block():
    # print(sup.table)
    if sup.table[0] == 1:  # 当前只剩一块(存下一组的地址),将此块分出去,存的地址覆盖
        fore = sup.table[-1][-1][-1][0] - 1  # fore是被分出去的块号
        sup.table = sup.table[-1][0]
    else:
        fore = sup.table[-1].pop(0)
        # print(fore)
        sup.table[0] -= 1
    return fore


def add_date_block(k, i):
    fore = distribute_block()
    k[-1].append(fore)
    # block[k[0]].append(fore)
    i.blo.append(fore)


def add_index_block(a, i, j):
    index_block = distribute_block()  # 申请新的块作为索引块
    fore = distribute_block()
    k = [fore]
    for kk in range(j-1):
        k = list(k)
    a.append([index_block, k])
    # block[index_block] = [fore]
    i.blo.append(fore)


def add_tree(name, id):
    global now
    if now.left is None:  # 当前路径有其他文件
        # print(now.left.date)
        a = Tree(name, id)
        now.left = a
        a.parent = now
        a.level = now.level + 1
    else:
        last = now
        n = now.left
        while n is not None:
            # print(last, n)
            last = n
            n = n.right
        a = Tree(name, id)
        last.right = a
        a.parent = now
        a.level = now.level + 1


def distribute(i):
    if len(inode) < 3:  # 直接
        fore = distribute_block()
        inode.append(fore)
        i.blo.append(fore)
        if len(inode) == 3:
            index_block = distribute_block()  # 申请新的块作为索引块
            block[index_block] = []  # 索引块中储存索引
            inode.append([index_block, []])  # [1, [2, 3, 4]]
    elif len(inode) <= 6:  # 一级索引
        k = inode[-1]  # 最后的一个
        if len(k[-1]) < 3 or not k[-1]:
            add_date_block(k, i)
        else:  # 该块已满
            add_index_block(inode, i, 1)
        if len(inode) == 6 and len(inode[-1][-1]) == 3:
            index_block = distribute_block()
            inode.append([index_block, []])  # [5,
            #                    k:              [15,[[6,  [7,  8,  9]],
            #  [10, [11, 12, 13]],
            #                    kk:                  [14, [...]]]
    elif len(inode) <= 9:  # 二级索引
        if not inode[-1][-1]:
            index_block = distribute_block()
            inode[-1][-1] = [[index_block, []]]
        k = inode[-1][-1]
        kk = k[-1]
        # print(k)
        if len(k) <= 3:
            # print(kk[-1])
            if len(kk[-1]) < 3:
                add_date_block(kk, i)
            elif len(kk[-1]) == 3:
                if len(k) < 3:
                    add_index_block(k, i, 1)

                else:
                    index_block = distribute_block()
                    inode.append([index_block, []])
                    add_index_block(inode[-1][-1], i, 0)
                # print(inode)
        else:  # 当前索引块已满
            index_block = distribute_block()
            inode.append([index_block, []])
            add_index_block(inode[-1][-1], i, 0)
        # print(inode[-1][-1][-1][-1])
        if len(inode) == 9 and len(inode[-1][-1][-1][-1]) == 3:
            index_block = distribute_block()
            inode.append([index_block, []])  # [5,
            #                    k:              [15,[[6,  [7,  8,  9]],
            #                                         [10, [11, 12, 13]],
            #                    kk:                  [14, [...]]]
        elif len(inode) <= 9:  # 二级索引
            if not inode[-1][-1]:
                index_block = distribute_block()
                inode[-1][-1] = [[index_block, []]]
            k = inode[-1][-1]
            kk = k[-1]
            # print(k)
            if len(k) <= 3:
                # print(kk[-1])
                if len(kk[-1]) < 3:
                    add_date_block(kk, i)
                elif len(kk[-1]) == 3:
                    if len(k) < 3:
                        add_index_block(k, i, 1)

                    else:
                        index_block = distribute_block()
                        inode.append([index_block, []])
                        add_index_block(inode[-1][-1], i, 0)
                    # print(inode)
            else:  # 当前索引块已满
                index_block = distribute_block()
                inode.append([index_block, []])
                add_index_block(inode[-1][-1], i, 0)
            # print(inode[-1][-1][-1][-1])
            if len(inode) == 9 and len(inode[-1][-1][-1][-1]) == 3:
                index_block = distribute_block()
                inode.append([index_block, []])
        #                                     [1, [[2, [[3, [4, 5,  6],
        #                                               [7, [8, 9, 10],
        #                                               [11,[12,13,14]]]
        #                                          [15,[[...]
        else:  # 三级索引
            if not inode[-1][-1]:
                index_block = distribute_block()
                inode[-1][-1] = [[index_block, []]]
            if not inode[-1][-1][-1]:
                index_block = distribute_block()
                inode[-1][-1][-1] = [[index_block, []]]
            if not inode[-1][-1][-1][-1]:
                index_block = distribute_block()
                inode[-1][-1][-1][-1] = [[index_block, []]]
            if not inode[-1][-1][-1][-1][-1]:
                index_block = distribute_block()
                inode[-1][-1][-1][-1][-1] = [[index_block, []]]

            a = inode[-1][-1]
            k = a[-1]
            kk = k[-1]
            kkk = kk[-1]
            print(a)
            if len(a) <= 3:
                if len(kk) <= 3:
                    print('kkk' + str(kkk))
                    if len(kkk[-1]) < 3 or not kkk[-1]:
                        print(222)
                        add_date_block(kkk, i)

                    elif len(kkk[-1]) == 3:
                        print(111)
                        print(k)
                        # if len(a) < 3:
                        if len(kk) < 3:
                            add_index_block(kk, i, 1)
                        else:
                            index_block = distribute_block()
                            inode[-1][-1].append([index_block, []])
                            add_index_block(inode[-1][-1][-1][-1], i, 0)
                        # else:

                else:  # k满了
                    index_block = distribute_block()
                    inode.append([index_block, []])
                    add_index_block(inode[-1][-1][-1][-1], i, 0)
            else:
                pass


def create_file(name, length, doc):  # doc:当前目录的inode
    if name not in doc.file:
        if sup.unused_block >= length:  # 如果有足够的空闲的块
            t = time.asctime(time.localtime(time.time()))
            i = INode(0)
            inode_table.append(i)  # 新建的inode加入列表
            global inode
            doc.file[name] = inode_table.index(i)
            i.id = inode_table.index(i)
            i.size = length
            i.time = t
            for j in range(length):
                distribute(i)
            # print(i.blo)
            add_tree(name, i.id)

        else:
            print('没有足够的空间!')
    else:
        print('文件已存在!')
    return doc


def create_doc(name, doc):
    if name not in doc.file:
        if sup.unused_block >= 1:
            t = time.asctime(time.localtime(time.time()))
            i = INode(1)
            inode_table.append(i)
            doc.file[name] = inode_table.index(i)
            i.id = inode_table.index(i)
            i.size = 1
            i.time = t
            distribute(i)
            add_tree(name, i.id)

        else:
            print('没有足够的空间!')
    else:
        print('文件已存在!')
    return doc


def change_doc(name, doc):
    global inode_table
    if name != '..':
        try:
            blo = doc.file[name]  # 该路径所占的inode块号
            blo = inode_table[blo]  # 当前路径的inode
            if blo.type == 1:  # 说明是路径
                global now_spr, now
                now_spr += '/' + name
                # print(now.date)
                if now.left.date == name:
                    now = now.left
                else:
                    # l = now
                    n = now.left
                    while n is not None:
                        if n.date == name:
                            break
                        # l = n
                        n = n.right
                    if n.date == name:
                        now = n
                # print(blo.file)
                return blo
            else:  # 有该名称的文件,但不是目录
                print('不存在该路径!')
        except KeyError:
            print('不存在该路径!')
    else:
        if now.date == 'root':
            return doc
        # print(now.date)
        now = now.parent
        i = inode_table[now.inode_num]
        # print(now.inode_num)
        now_spr = '/'.join(now_spr.split('/')[:-1])
        return I


def ls(doc):
    for i in doc:
        ino = inode_table[doc[I]]
        type = ''
        if ino.type == 1:
            type = '<dir>'
        print("%10s %8s %10s %5d" % (ino.time, type, i, ino.size))


def remove(name, doc):
    global sup
    if name in doc.file:
        blo = doc.file[name]  # inode号
        blo = inode_table[blo].blo  # 所占的块号
        if blo.type == 0 or (blo.type == 1 and not blo.file):
            del doc.file[name]
            for i in blo:
                if sup.table[0] != 10:
                    print(sup.table)
                    sup.table[-1].insert(0, i)
                    sup.table[0] += 1
                else:
                    print(sup.table)
                    sup.table[0] = 1
                    sup.table[-1] = [[10, sup.table[-1]]]
        else:
            print('无法删除!')
    else:
        print('没有该文件!')


if __name__ == '__main__':
    all, block_size = 500000, 1024
    num = math.ceil(all / block_size)
    block = [-1] * int(num)
    sup = SuperBlock()
    sup.initial(num)
    i = INode(1)  # 当前目录的inode
    i.blo = 0
    i.size = 1
    i.time = time.asctime(time.localtime(time.time()))
    inode_table.append(i)
    sup.table[0] -= 1
    sup.table[-1].pop(0)
    block[0] = -2
    root = Tree('root', 0)
    now = root
    now_spr = 'root'
    inode = []  #
    while True:
        command = input(now_spr+'/$ ').split()
        try:
            if command[0] == 'mkdir':
                create_doc(command[1], i)
            elif command[0] == 'cd':
                i = change_doc(command[1], i)
            elif command[0] == 'rm':
                remove(command[1], i)
            elif command[0] == 'mk':
                create_file(command[1], math.ceil(int(command[2])/block_size), i)
            elif command[0] == 'ls':
                print(inode)
                ls(i.file)
            elif command[0] == 'tree':
                print(now.level*'   '+now.date)
                preorder(now.left)
                print()
            else:
                print('没有该命令!')
        except Exception:
            print('没有该命令!')
            # print(Exception)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341