操作系统实践2022独立开发者

Linux 环境下基于 C/C++ 的模拟命令解释器

通过 C++ 与 POSIX API,重新实现目录浏览、文件复制、递归查找等 12 项 Linux 命令核心行为,理解命令背后的文件系统与系统接口。

C++LinuxPOSIX APIFilesystemDirectory StreamFile Descriptor
ARCHIVE / 2022系统调用与文件系统

把常见命令拆成可验证的系统接口调用。

mypwdmylistmycdmycpmyfind
↓
命令函数解析并分发
↓
getcwdopendir / readdirchdirread / writeftw
↓
LINUX FILESYSTEM目录、文件与文件树
12 项命令的核心行为,通过 C++ 与 Linux C / POSIX APIs 实现。

01 / 项目快照

角色

独立开发者

场景

操作系统实践

环境

Linux · VMware

语言

C++ · Linux C / POSIX APIs

范围

12 项模拟命令

核心领域

文件系统 · 目录流 · 文件描述符 · 文件树遍历

02 / 项目目标

理解 Linux 命令背后的系统调用。

这不是完整 POSIX shell,也不是通过 system() 调用 ls 或 cp 的封装。报告中的 C++ 实现直接调用 Linux / POSIX C 函数库,重新实现目录浏览、目录切换、文件复制、递归查找等命令的核心行为。

03 / 命令实现

12 项命令,逐个拆分实现。

课程报告记录了 10 项基础命令和 2 项扩展命令,最终实现共 12 项功能。

命令目的核心接口
mypwd

显示当前工作目录

getcwd()
mylist

列出目录内容

opendir() · readdir() · closedir()
mycd

切换当前目录

chdir()
mymkdir

新建目录

mkdir()
myrmdir

删除目录

rmdir()
mycp

复制文件的核心行为

open() · read() · write()
myrename

重命名文件或目录

rename()
myfind

递归查找文件

ftw()
mydate

显示当前系统时间

time() · ctime()
mycreate

创建并写入文本文件

ofstream
mydelete

删除文本文件

remove()
exit

退出解释器

—

04 / 系统如何工作

输入命令,分发函数,操作文件系统。

mypwdmylistmycdmycpmyfind
↓
命令函数解析并分发
↓
getcwdopendir / readdirchdirread / writeftw
↓
LINUX FILESYSTEM目录、文件与文件树

每个命令先被拆成独立函数,再调用对应的目录、文件或文件树接口。这种分解让复杂任务可以逐项理解、实现和手动验证。

05 / 目录流操作

不是执行 ls,而是直接遍历目录流。

mylist() 用 opendir() 打开指定目录并取得 DIR*,用 readdir() 逐个读取 struct dirent 节点,最后通过 closedir() 释放目录流。

DIR* d = opendir(dir.c_str());
if (d == NULL) return false;

struct dirent *dirent;
while (dirent = readdir(d)) {
  cout << dirent->d_name;
}
closedir(d);

06 / 文件描述符与复制

open → read → write。

mycopy() 使用整型文件描述符和 char buf[1024] 读取源文件并写入目标文件。报告中的实现还处理了目标已存在的情况:先询问是否覆盖;若不覆盖,则为新文件名追加 (1)。

fo1 = open(existname.c_str(), O_RDONLY);
fo2 = open(newname.c_str(), O_WRONLY | O_CREAT, S_IRWXU);
int size = read(fo1, buf, sizeof(buf));
write(fo2, buf, size);
close(fo1);
close(fo2);

07 / 递归文件搜索

沿文件树逐层查找目标文件。

Directory├── Folder A│   └── target.txt└── Folder B
↓
ftw()callback fn()path + stat + type
↓
匹配文件名输出匹配路径

myfind() 调用 ftw() 递归遍历指定目录及其子目录。每到一个节点,ftw() 将路径、stat 信息和节点类型交给 callback fn();fn() 对比目标文件名并输出匹配路径。

int fn(const char *fpath, const struct stat *st, int typeflag) {
  // compare the path tail with the target filename
  if (typeflag == FTW_F) cout << fpath;
  return 0;
}

ftw(dir, fn, depth);

08 / 核心系统接口

Directory

getcwd · opendir · readdir · closedir · chdir · mkdir · rmdir

File

open · read · write · close · remove · rename

Traversal

ftw · stat · dirent

Time

time · ctime

09 / 实现证据

用原始代码说明实现,而不是制造截图。

原报告没有可公开的终端或 VMware 运行截图。因此此处只保留报告中可以核实的核心代码与说明,作为实现证据。

01

目录列出

DIR* d = opendir(dir.c_str());
if (d == NULL) return false;

struct dirent *dirent;
while (dirent = readdir(d)) {
  cout << dirent->d_name;
}
closedir(d);

mylist() 直接打开目录流、逐个读取 dirent 节点,再关闭目录流;它不是执行 ls 的封装。

02

目录切换

bool mycd(string path) {
  if (chdir(path.c_str()) == 0) {
    return true;
  }
  return false;
}

mycd() 通过 chdir() 改变当前工作目录,并以返回值表达切换是否成功。

03

文件复制

fo1 = open(existname.c_str(), O_RDONLY);
fo2 = open(newname.c_str(), O_WRONLY | O_CREAT, S_IRWXU);
int size = read(fo1, buf, sizeof(buf));
write(fo2, buf, size);
close(fo1);
close(fo2);

mycopy() 使用文件描述符和 1024-byte buffer 实现 open → read → write。目标已存在时,报告中的实现会询问是否覆盖;不覆盖则在新文件名后追加 (1)。

04

递归查找

int fn(const char *fpath, const struct stat *st, int typeflag) {
  // compare the path tail with the target filename
  if (typeflag == FTW_F) cout << fpath;
  return 0;
}

ftw(dir, fn, depth);

myfind() 通过 ftw() 遍历指定目录及其子目录;每个节点把路径、stat 信息与类型交给 callback fn(),由它判断文件名并输出匹配路径。

05

创建与删除

ofstream out;
out.open(filename, std::ios::out | std::ios::app);
out << str;
out.close();

if (remove(name) == 0) {
  cout << "file delete success";
}

mycreate() 用 ofstream 写入输入文本;mydelete() 对文件名调用 remove() 并报告结果。

10 / 环境与调试

在 Linux / VMware 环境中完成编译与调试。

报告记录了两项环境问题:VMware 虚拟机启动黑屏,经 BIOS / firmware 中调整 VMware Virtual SCSI Hard Drive 的启动优先级解决;进入 Linux 后发现未安装 g++,随后按提示使用 apt 安装编译器。这些经历属于开发环境排障,而非命令解释器功能本身。

11 / 现在回看

这个项目让我开始理解:pwd、ls、cd、cp 和文件查找并不是黑盒,它们可以拆解为目录流、文件描述符、文件树遍历和系统接口调用。

当时最有效的策略,是把一个看起来复杂的解释器拆成一个个可以独立验证的命令。报告记录了多轮手动调试,未发现阻断已实现命令集的核心问题。今天重新实现时,我会进一步分离命令解析、参数校验、错误处理和系统调用封装,并加入自动化测试与统一错误返回;这些属于今天对 2022 年作品的反思,而非当时已实现的能力。

下一个案例

小区物业管理系统

↗