一、Shell的工作流程

Shell的核心逻辑是一个循环处理流程:读取输入→解析命令→执行命令→显示结果。这个过程类似于餐厅的点餐系统,顾客下单(输入命令),厨房处理订单(解析执行),最后上菜(输出结果)。

核心代码框架如下:

while (1) {
    print_prompt();          // 显示提示符
    read_command();          // 读取输入
    parse_command();         // 解析命令
    execute_command();       // 执行命令
}

二、彩色提示符的实现

彩色提示符需要组合系统信息和ANSI颜色代码。就像汽车仪表盘,不同信息需要不同颜色突出显示。

关键实现步骤:

// 获取用户信息
uid_t uid = getuid();
char* user = getpwuid(uid)->pw_name;

// 获取主机名
char hostname[1024];
gethostname(hostname, sizeof(hostname));

// 获取当前目录
char cwd[1024];
getcwd(cwd, sizeof(cwd));

// ANSI颜色代码
#define COLOR_RED "\033[31m"
#define COLOR_RESET "\033[0m"

printf("[%s%s@%s%s] %s$ ", 
    COLOR_RED, user, hostname, COLOR_RESET, cwd);

三、命令解析模块

命令解析使用strtok()分割字符串,就像用剪刀裁剪布料。需要注意strtok()会修改原始字符串,且不是线程安全的。

典型实现:

char* args[MAX_ARGS];
char* token = strtok(input, " ");
int i = 0;

while (token != NULL) {
    args[i++] = token;
    token = strtok(NULL, " ");
}
args[i] = NULL; // execvp需要NULL结尾

四、内置命令处理

内置命令必须由Shell自身实现,就像人体无法外包消化的功能。cd命令典型实现:

if (strcmp(args[0], "cd") == 0) {
    if (args[1] == NULL) {
        chdir(getenv("HOME"));
    } else {
        if (chdir(args[1]) != 0) {
            perror("cd failed");
        }
    }
    return 1; // 标记为已处理的内置命令
}

五、外部命令执行

外部命令通过fork-exec模型执行,就像细胞分裂产生新生命:

pid_t pid = fork();

if (pid == 0) { // 子进程
    execvp(args[0], args);
    perror("exec failed");
    exit(1);
} else if (pid > 0) { // 父进程
    wait(NULL); // 等待子进程结束
} else {
    perror("fork failed");
}

六、迷你Shell vs 标准Bash对比
功能特性迷你Shell标准Bash
彩色提示符
管道支持
重定向
后台运行
脚本支持

完整示例代码结构:

#include <unistd.h>
#include <sys/wait.h>
#include <pwd.h>

// 各功能函数声明
void print_prompt();
void read_command();
void parse_command();
int execute_command();

int main() {
    while (1) {
        print_prompt();
        read_command();
        parse_command();
        if (execute_command() == 0) {
            break; // 处理exit命令
        }
    }
    return 0;
}

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐