从零开始编写 Linux 自定义 Shell
Shell 是用户与操作系统内核交互的命令行界面。它充当中介,解析用户输入并传递给内核执行。虽然 Bash 是最常用的 Shell,但理解其底层原理对于掌握操作系统至关重要。本章我们将基于 Linux 环境,用 C++ 手写一个简易的 Shell 解释器。
运行原理
要实现一个 Shell,首先要理解它的生命周期。典型的 Shell 交互流程如下:
- 读取输入:从标准输入(键盘)读取一行命令。
- 创建子进程:调用
fork()创建一个新进程。 - 执行命令:在子进程中通过
exec系列函数替换当前程序映像。 - 等待退出:父进程调用
waitpid()等待子进程结束。 - 循环往复:处理完一条命令后,回到第一步继续等待下一条。
这个过程构成了 Shell 的核心骨架。接下来我们一步步填充细节。
实现步骤
为了简化操作,我们采用 C/C++ 混编的方式,主体逻辑使用 C 语言接口,辅以 C++ 的字符串处理能力。所有代码将放在一个 .cc 文件中。
1. 打印提示符
Shell 启动后通常会显示类似 [user@host ~]$ 的提示符。我们需要获取环境变量中的用户名、主机名和当前工作目录来构建这个字符串。
#include <cstdlib>
#include <cstdio>
#include <string>
#define SLASH "/"
// 获取当前工作路径
const char* GetPwd() {
const char* pwd = getenv("PWD");
return pwd == NULL ? "None" : pwd;
}
// 获取主机名
const char* GetHostName() {
const char* hostname = getenv();
hostname == ? : hostname;
}
{
* user = ();
user == ? : user;
}
{
std::string dir = pwd;
(dir == SLASH) SLASH;
pos = dir.(SLASH);
(pos == std::string::npos) ;
dir.(pos + );
}
{
(out, size, FORMAT, (), (), (()).());
}
{
prompt[CMDLINE_MAX];
(prompt, CMDLINE_MAX);
(, prompt);
(stdout);
}


