首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言實戰:從零手寫一個簡易 Shell (DIY Shell)

     編輯:關於C

專案目標

實作一個極簡 Shell,支援提示符顯示、命令讀取、內建命令(exit、cd、ls)解析執行、未知命令提示、循環執行直到 exit。這是理解進程控制、字串解析、系統呼叫的最佳入門專案。

核心架構

  1. 提示符:印出 |-> 模擬 $。
  2. 讀取輸入:使用 fgets(buf, SIZE, stdin) 安全讀取整行,避免緩衝區溢位。
  3. 命令解析:建立命令表結構體陣列,包含命令字串、長度、處理函式指標。
  4. 匹配執行:遍歷命令表,strncmp 比對前綴,匹配則呼叫對應 handler。
  5. 循環:旗標控制 while(flag),exit 將旗標歸零結束。

關鍵程式碼骨架

#define BUF_SIZE 256
#define CMD_NUM 3

typedef struct {
    const char *str;
    size_t size;
    void (*handler)(char *);
} Command;

void cmd_exit(char *arg) { /* 設定全域 flag=0 */ }
void cmd_cd(char *arg) { /* chdir(arg) 實作 */ }
void cmd_ls(char *arg) { /* system("ls") 或 opendir/readdir 實作 */ }

Command cmd_tbl[CMD_NUM] = {
    {"exit", 4, cmd_exit},
    {"cd",   2, cmd_cd},
    {"ls",   2, cmd_ls}
};

int main() {
    char buf[BUF_SIZE];
    int flag = 1;
    while (flag) {
        printf("|->");
        if (!fgets(buf, BUF_SIZE, stdin)) break;
        // 移除尾部 \n
        buf[strcspn(buf, "\n")] = '\0';
        
        int found = 0;
        for (int i = 0; i < CMD_NUM; i++) {
            if (strncmp(buf, cmd_tbl[i].str, cmd_tbl[i].size) == 0 &&
                (buf[cmd_tbl[i].size] == '\0' || buf[cmd_tbl[i].size] == ' ')) {
                cmd_tbl[i].handler(buf + cmd_tbl[i].size);
                found = 1;
                break;
            }
        }
        if (!found) printf("can't find command: %s\n", buf);
    }
    return 0;
}

擴展方向

  • 支援參數解析(strtok 分割 argv)。
  • 實作外部命令執行(fork + execvp)。
  • 支援管道、重導向、背景執行(&)。
  • 加入歷史指令、Tab 補全(需 readline 庫)。

執行範例

|->abc
can't find command: abc
|->cd /tmp
cd running
|->ls
ls running
|->exit

心得

Shell 的本質是「讀取-解析-執行」無限循環。從這個微型專案出發,逐步加入進程管理、信號處理、作業控制,即可理解現代 Shell (bash/zsh) 的核心架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved