模拟文件系统(操作系统大作业)

前言

​ 在操作系统课程中,期末结束大作业是从一下几个方向选一个题目去做大作业(也可自选自拟类似题目,不仅限于以下所列)

  • 使用Linux多线程模型,设计并实现多线程的任务协作应用,并验证;
  • 分析死锁模型,设计实现不同的死锁检测和银行家算法;
  • 设计实现Linux下的多进程应用,并设计、对比和验证Linux下局部和全局页面置换算法的差异;
  • 设计实现一个模拟的文件系统,并对其进行基本功能的验证;
  • 设计实现不同的磁盘臂调度算法,并设计实现Linux下的驱动程序加以验证;

​ 最终我选择的是【设计实现一个模拟的文件系统,并对其进行基本功能的验证】,一下内容都是根据这个题目所完成!

1 设计目标

​ 本项目的目标是设计并实现一个简单的模拟文件系统,支持常见的文件与目录操作,包括创建、删除、读取文件,以及切换、列出目录内容等操作,通过编程实现文件系统的基本管理功能,培养对操作系统课程中的文件系统工作机制的理解。

2 功能描述

2.1 操作命令

1
2
3
4
5
6
7
8
9
10
11
12
查看当前目录: 	ls <目录名>
改变目录: cd <目录名>
创建文件: touch <文件名>
创建目录: mkdir <目录名>
写入文件: write <文件名> <内容>
读取文件: read <文件名>
删除文件: rmfile <文件名>
删除目录: rmdir <目录名>
查看当前路径: pwd
显示目录内容: ls <目录名>
重命名文件: rename <文件名>
退出文件系统: exit system

2.2 交互界面

​ 提供直观的命令提示和操作反馈,包括错误提示、成功提示等,输出风格友好、美观。

2.3 文件结构

​ 通过内存中的对象来模拟文件系统,支持文件和目录的基本操作。

3 总体设计

3.1 模块划分

  • 输出模块:用于处理不同类型的输出(如信息、错误、提示等)。
  • 文件与目录模块:定义 File 和 Directory 类,用于管理文件内容和目录结构。
  • 文件系统模块:实现文件系统的整体逻辑,包括路径管理、命令解析和操作调用。
  • 主交互模块:用户输入解析和系统命令调用。

3.2 系统流程

  • 用户输入命令,系统根据输入解析出操作类型及参数。
  • 调用文件系统模块执行相应操作,并输出结果。
  • 支持多层次目录结构,能动态创建、删除文件及文件夹。

4 详细设计

4.1 功能模块设计

4.1.1 文件类 (File)

属性:文件名、内容。

方法:

  • 写入内容:write(content)
  • 读取内容:read()

4.1.2 目录类 (Directory)

属性:目录名、父目录、子目录列表、文件列表。

方法:

  • 创建文件/目录。
  • 删除文件/目录。
  • 列出目录内容。
  • 修改文件名。
  • 写入/读取文件。

4.1.3 文件系统类 (FileSystem)

属性:根目录、当前目录。

方法:

  • 切换目录:cd(name)
  • 显示目录内容:ls(name)
  • 创建文件/目录:touch(name)、mkdir(name)
  • 写入/读取文件:write(name, content)、read(name)
  • 删除文件/目录:rmfile(name)、rmdir(name)
  • 查看当前路径:pwd()
  • 重命名文件:rename(oldname, new name)

4.1.4 输出类 (Output)

提供不同风格的输出方法:

  • 错误输出(红色):error(output)
  • 信息输出(绿色):info(output)
  • 提示输出(蓝色):hint(output)

4.2 系统交互流程图

image-20241206164544890

5 实现

5.1 编译截图

img

5.2 运行截图

5.2.1 启动界面

img 5.2.2 创建文件

img

5.2.3 创建目录

img

5.2.4 写入文件

img

5.2.5 读取文件

img

5.2.6 删除文件

img

5.2.7 删除目录

img

5.2.8 改变目录

img

img 5.2.9 当前目录

img

5.2.10 当前路径

img

5.2.11 重命名文件

img

5.2.12 退出系统

img

5.2.13 命令错误

img

6 代码附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# 开始页面
BANNER = """
============================================================
欢迎来到模拟文件系统!
============================================================
功能如下:
查看当前目录: ls
改变目录格式: cd <目录名>
创建文件格式: touch <文件名>
创建目录格式: mkdir <目录名>
写入文件格式: write <文件名> <内容>
读取文件格式: read <文件名>
删除文件格式: rmfile <文件名>
删除目录格式: rmdir <目录名>
查看当前路径格式: pwd
重命名文件格式: rename <文件名>
退出文件系统: exit system
------------------------------------------------------------
"""

# 输出类
class Output:
def __init__(self, output):
pass

# 错误输出 红色
@staticmethod
def error(output):
print(f"\033[31m{output}\033[0m")

# 信息输出 绿色
@staticmethod
def info(output):
print(f"\033[36m{output}\033[0m")

# 提示输出 蓝色
@staticmethod
def hint(output):
print(f"\033[34m{output}\033[0m")

# 警告输出 黄色
@staticmethod
def warn(output):
print(f"\033[33m{output}\033[0m")

# 功能介绍 淡紫色
@staticmethod
def func(output):
print(f"\033[35m{output}\033[0m")

# 文件类
class File:
def __init__(self, name, content=""):
self.name = name
self.content = content

def write(self, content):
self.content = content

def read(self):
return self.content

# 目录类
class Directory:
def __init__(self, name, parent):
self.name = name
self.parent = parent
self.subdirs = {}
self.files = {}

# 创建文件
def create_file(self, name, content=""):
if name not in self.files:
self.files[name] = File(name, content)
Output.info(f"文件“{name}”创建成功!")
else:
Output.error(f"错误:文件“{name}”已经存在!")

# 创建文件夹
def create_subdir(self, name, parent):
if name not in self.subdirs:
self.subdirs[name] = Directory(name, parent)
Output.info(f"文件夹“{name}”创建成功!")
else:
Output.error(f"错误:文件夹“{name}”已经存在!")

# 删除文件
def delete_file(self, name):
if name in self.files:
self.files.pop(name)
Output.info(f"文件“{name}”删除成功!")
else:
Output.error(f"错误:文件“{name}”不存在!")

# 删除文件夹
def delete_subdir(self, name):
if name in self.subdirs:
self.subdirs.pop(name)
Output.info(f"文件夹“{name}”删除成功!")
else:
Output.error(f"错误:文件夹“{name}”不存在!")

# 列出文件
def list_contents(self):
Output.warn(f"文件夹“{self.name}”所包含内容如下:")
for subdir in self.subdirs:
Output.info(f"[DIR] {subdir}")
for file in self.files:
Output.info(f"[FILE] {file}")

# 修改文件名
def rename_file(self, old_name, new_name):
if old_name in self.files:
self.files[new_name] = self.files.pop(old_name)
# self.files[new_name] = self.files[old_name]
# self.files.pop(old_name)
self.files[new_name].name = new_name
Output.info(f"文件名修改成功!{old_name} -> {new_name}")
else:
Output.error(f"错误:文件“{old_name}”不存在!")

# 写入文件
def write_file(self, name, content):
if name not in self.files:
self.files[name] = File(name, content)
Output.warn(f"文件“{name}”创建成功,并且已写入文件!")
else:
self.files[name].write(content)
Output.info(f"文件“{name}”写入成功!")

# 读取文件
def read_file(self, name):
if name not in self.files:
Output.error(f"错误:文件“{name}”不存在!")
elif self.files[name].content == "":
Output.warn(f"提示:文件“{name}”为空!")
else:
Output.warn(f"文件“{name}”内容如下:")
Output.info(self.files[name].read())


# 文件系统类
class FileSystem:
def __init__(self):
self.root = Directory("~", parent=None)
self.current = self.root

# 切换目录
def cd(self, name):
if name == "..":
if not self.current.parent:
Output.error(f"错误:当前已在根目录,无法向上切换目录!")
else:
self.current = self.current.parent
Output.info(f"目录切换成功,当前目录为:{self.current.name}")
elif name in self.current.subdirs:
self.current = self.current.subdirs[name]
Output.warn(f"目录切换成功,当前目录为:{self.current.name}")
else:
Output.error(f"错误:未找到目录“{name}”,请检查目录名是否正确!")

# 查看文件夹
def ls(self, name):
if not name:
self.current.list_contents()
# elif name in self.current.subdirsmk:
# self.current = self.current.files[name]
# self.current.list_contents()
# self.cd("..")
else:
Output.warn(f"错误:命令错误,请重试mkdi!")

# 创建文件
def touch(self, name):
self.current.create_file(name)

# 创建文件
def mkdir(self, name):
self.current.create_subdir(name, self.current)

# 写入文件
def write(self, name, content):
self.current.write_file(name, content)

# 读取文件
def read(self, name):
self.current.read_file(name)

# 查看当前路径
# def pwd(self):
# temp = self
# pwd_path = temp.current.name
# temp.current = temp.current.parent
# while temp.current.parent:
# pwd_path = temp.current.name + "/" + pwd_path
# temp.current = temp.current.parent
# print(f"当前路径为:{pwd_path}")

# 查看当前路径
def pwd(self):
current = self.current # 获取当前目录
path_parts = []

# 从当前目录向上追溯直到根目录
while current is not None:
path_parts.insert(0, current.name) # 将当前目录名称添加到路径部分
current = getattr(current, "parent", None) # 获取父目录,若不存在则为 None

# 拼接路径并输出
pwd_path = "/".join(path_parts)
Output.warn(f"当前路径为:/{pwd_path}")

# 删除文件
def rmfile(self, name):
self.current.delete_file(name)

# 删除文件夹
def rmdir(self, name):
self.current.delete_subdir(name)

# 修改文件名
def rename(self, old_name, new_name):
self.current.rename_file(old_name, new_name)

def main():
Output.func(BANNER)

fs = FileSystem()
while True:
user_input = input("\033[34m请输入文件操作命令:\033[0m")
if user_input == "exit system":
Output.error("再见!退出模拟文件系统。")
break
# elif "ls" in user_input:e
# if " " in user_input:
# user_order, user_param = user_input.split(" ")
# user_order, user_param = user_input, ""
# elif "write" in user_input:
# user_order, user_param, user_content = user_input.split(" ")
# elif "pwd" in user_input:
# user_order, user_param = user_input, ""
# else:
# try:
# user_order, user_param = user_input.split(" ")
# except ValueError:
# Output.error("错误:命令或参数残缺!")

try:
# 根据不同命令类型解析参数
if user_input.startswith("write") or user_input.startswith("rename"):
parts = user_input.split(" ", 2)
if len(parts) == 3:
user_order, user_param, user_content = parts
else:
Output.error("错误:命令参数不足!")
continue
elif " " in user_input:
user_order, user_param = user_input.split(" ", 1)
else:
user_order = user_input.strip()
user_param = ""
# 查看文件目录
if user_order == "ls":
fs.ls(user_param)
# 切换文件目录
elif user_order == "cd":
fs.cd(user_param)
# 创建文件夹
elif user_order == "mkdir":
fs.mkdir(user_param)
# 创建文件
elif user_order == "touch":
fs.touch(user_param)
# 写入文件
elif user_order == "write":
fs.write(user_param, user_content)
# 读取文件
elif user_order == "read":
fs.read(user_param)
# 查看路径
elif user_order == "pwd":
fs.pwd()
# 删除文件
elif user_order == "rmfile":
fs.rmfile(user_param)
# 删除文件夹
elif user_order == "rmdir":
fs.rmdir(user_param)
# 修改文件名
elif user_order == "rename":
fs.rename(user_param, user_content)
else:
Output.error("错误:无效的命令或参数,请重试!")
except ValueError as ve:
Output.error(f"命令解析错误:{ve}")
except Exception as e:
Output.errorsl(f"系统错误:{e}")


if __name__ == '__main__':
main()