当前位置: 首页 > news >正文

在 Linux 中使用 Vim 和 C++ 实现一个基本 Shell

引言

想象这样一个场景:

  • 你刚入职一家科技公司,被要求开发一个简单的 Shell

  • 需要在 Linux 环境下使用 Vim 和 C++ 完成这个任务

  • 你对 Shell 的实现原理还不熟悉,面对空白屏幕不知所措

别担心!本文将带你从零开始,使用 Vim 和 C++ 实现一个基本的 Shell,让你深入理解 Shell 的工作原理。


一、环境准备

1. 安装必要工具
sudo apt update
sudo apt install vim g++ build-essential
2. 创建项目目录
mkdir myshell
cd myshell
3. 使用 Vim 创建源文件
vim myshell.cpp

二、Shell 的基本结构

1. 主循环

Shell 的核心是一个读取-解析-执行循环(Read-Eval-Print Loop, REPL)。

#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/wait.h>

void parse_command(const std::string& input, std::vector<std::string>& args) {
    size_t prev = 0, pos;
    while ((pos = input.find(' ', prev)) != std::string::npos) {
        if (pos > prev) {
            args.push_back(input.substr(prev, pos - prev));
        }
        prev = pos + 1;
    }
    if (prev < input.length()) {
        args.push_back(input.substr(prev, std::string::npos));
    }
}

int main() {
    std::string input;
    while (true) {
        std::cout << "mysh> ";
        std::getline(std::cin, input);
        if (input.empty()) continue;

        std::vector<std::string> args;
        parse_command(input, args);

        if (args[0] == "exit") {
            break;
        }

        // 执行命令
        pid_t pid = fork();
        if (pid == 0) {
            // 子进程
            std::vector<char*> argv;
            for (auto& arg : args) {
                argv.push_back(&arg[0]);
            }
            argv.push_back(nullptr);
            execvp(argv[0], argv.data());
            std::cerr << "Command not found: " << args[0] << std::endl;
            _exit(1);
        } else if (pid > 0) {
            // 父进程
            int status;
            waitpid(pid, &status, 0);
            if (WIFEXITED(status)) {
                std::cout << "Process exited with code " << WEXITSTATUS(status) << std::endl;
            }
        } else {
            std::cerr << "Fork failed!" << std::endl;
        }
    }
    return 0;
}
2. 编译和运行
g++ -o myshell myshell.cpp
./myshell

三、功能扩展

1. 内置命令

实现一些内置命令,如 cd 和 help

void execute_builtin(const std::vector<std::string>& args) {
    if (args[0] == "cd") {
        if (args.size() < 2) {
            std::cerr << "cd: missing argument" << std::endl;
        } else if (chdir(args[1].c_str()) != 0) {
            perror("cd");
        }
    } else if (args[0] == "help") {
        std::cout << "Simple Shell\n"
                  << "Built-in commands:\n"
                  << "  cd <dir>    Change directory\n"
                  << "  help        Show this help message\n"
                  << "  exit        Exit the shell\n";
    } else {
        std::cerr << "Unknown built-in command: " << args[0] << std::endl;
    }
}

int main() {
    std::string input;
    while (true) {
        std::cout << "mysh> ";
        std::getline(std::cin, input);
        if (input.empty()) continue;

        std::vector<std::string> args;
        parse_command(input, args);

        if (args[0] == "exit") {
            break;
        } else if (args[0] == "cd" || args[0] == "help") {
            execute_builtin(args);
        } else {
            // 执行外部命令
            pid_t pid = fork();
            if (pid == 0) {
                // 子进程
                std::vector<char*> argv;
                for (auto& arg : args) {
                    argv.push_back(&arg[0]);
                }
                argv.push_back(nullptr);
                execvp(argv[0], argv.data());
                std::cerr << "Command not found: " << args[0] << std::endl;
                _exit(1);
            } else if (pid > 0) {
                // 父进程
                int status;
                waitpid(pid, &status, 0);
                if (WIFEXITED(status)) {
                    std::cout << "Process exited with code " << WEXITSTATUS(status) << std::endl;
                }
            } else {
                std::cerr << "Fork failed!" << std::endl;
            }
        }
    }
    return 0;
}

四、测试与调试

1. 编译和运行
g++ -o myshell myshell.cpp
./myshell
2. 测试命令
mysh> ls
mysh> cd /tmp
mysh> pwd
mysh> help
mysh> exit

五、高级话题与性能优化

1. 命令历史

实现命令历史功能,使用上下箭头键浏览历史命令。

2. 自动补全

实现命令和路径的自动补全功能。

3. 管道和重定向

支持管道(|)和重定向(><)操作。


结语

通过本文的学习,你已经掌握了使用 Vim 和 C++ 实现一个基本 Shell 的方法。无论是开发系统工具,还是深入理解操作系统原理,这些知识都将成为你的强大武器。记住,理解 Shell 的实现原理不仅有助于编写更好的代码,更能深入理解操作系统的设计哲学。

相关文章:

  • C语言三大程序结构 单分支语句
  • 【开源宝藏】30天学会CSS - DAY6 第六课 流光文字动画
  • 组合模式 (Composite Pattern)
  • XSS-Labs 靶场 Level 0-10关卡 WriteUp
  • 第九章 | Solidity 设计模式与 Gas 优化实战
  • 生活电子常识-deepseek-r1本地化部署+ui界面搭建
  • 如何在百度搜索上删除与自己名字相关的资料
  • 一文详解Softmax与Sigmoid函数
  • 【MySQL】用户管理
  • 突破传统:探索函数命名的新视角
  • C语言-适配器模式详解与实践
  • Pydantic字段级校验:解锁@validator的12种应用
  • OpenFOAM中snappyHexMesh网格工具如何使用,有哪些使用技巧
  • 拉取镜像,推送到阿里云镜像仓库
  • WX小程序
  • mac丝滑安装Windows操作系统【丝滑简单免费】
  • 微前端qiankun框架的使用
  • 【Linux】信号:信号保存和处理
  • AI比人脑更强,因为被植入思维模型【18】万物系统思维模型
  • 如何通过less在vue2中达到切换皮肤的目的
  • 吉利汽车一季度净利润大增264%,称整合极氪后实现整体效益超5%
  • 商务部回应美方加严限制中国芯片:敦促美方立即纠正错误做法
  • 今年有望投产里程已近3000公里,高铁冲刺谁在“狂飙”?
  • 杞支雅男评《1517》|放眼世界,立足德国
  • 欠债七十万后,一个乡镇驿站站长的中年心事
  • 玉渊谭天丨卢拉谈美国降低对华关税:中国的行动捍卫了主权