日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux(1)- 简单的 shell 解释器

發布時間:2025/6/17 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux(1)- 简单的 shell 解释器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??????真正了不起的程序員對自己程序的每一個字節都了如指掌。
??????計算機科學領域中,沒有什么問題是增加一個中間層解決不了的。

目錄

    • 做一個簡單的 Shell 解釋器
        • 環境
        • 思路
        • 具體實現目標
        • 方法
        • 完整代碼
        • 功能
        • 運行截圖

做一個簡單的 Shell 解釋器

環境

??????Ubuntu20.04 64位虛擬機

思路

??????如何做一個類似的 shell 解釋器,按照不用重復造輪子的思想,所以最直接的思路是:編寫接口利用現成的 bash 。這是主要的思想。

具體實現目標

??????1,需要做一個交互界面,能夠仿照正常的終端格式打印出提示符
??????2,需要處理用戶的輸入指令,能夠對用戶的命令進行處理

方法

??????1,包含于頭文件<pwd.h>下,在此需要用到的函數有三個,分別是 getpwuid() 獲取當前用戶名、gethostname() 獲取主機名和getcwd() 獲取當前路徑。如下:


#include<pwd.h>struct passwd* a = getpwuid(getuid());//獲得提示符char name[32];gethostname(name, 31);char current_dir[128];getcwd(current_dir, 127);...//a 是一個結構體,在此只需要訪問用戶名這一個成員。printf("%s@%s:%s$ ",a->pw_name,name,current_dir);//打印提示符


??????2,每當有用戶進行輸入時,采用 fork()創建一個子進程,讓子進程來執行具體的用戶輸入,執行完畢用 wait() 來回收子進程。

??????執行用戶輸入時,在此采用 exec 函數族中的 execvp(), 這個函數原型如下:
??????int execvp(const char *file, char *const argv[]);
??????關于返回值:該函數執行失敗則直接返回-1。
??????第一個參數是要運行的腳本文件,會在環境變量PATH中查找并執行,也就是說它可以直接對用戶輸入進行處理(比如 ls 命令),不需要進一步地轉化(將 ls 轉化為 /bin/ls ),用起來較為方便。
??????第二個參數是一個字符串數組,它是一個參數列表,下標為0,1,2…。注意:其中下標為0的參數是待執行的命令本身,也就是腳本文件名。
??????還需要注意字符串數組最后一個參數必須為 NULL。

??????舉例如下:
??????當用戶輸入命令 ls -l 時,我們所需要做的工作是:假設字符串數組名為 argv,令 argv[0]=“ls” ,令 argv[1]="-l" ,令 argv[2]=NULL 。然后采用函數調用方法為 execvp(argv[0],argv) 來執行 ls -l 命令。


??????如下是子進程中的代碼,用來處理用戶輸入: printf("my pid is %d,I will execute the task.\n\n", getpid());if (execvp(arg[0], arg) < 0)//執行用戶命令(如ls命令:exec函數中不帶p的需要采用/bin/ls形式,而帶p的會自動查找環境變量。){printf("error in execv().\n");exit(-1);}elseexit(0);

完整代碼

#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<string.h> #include<stdlib.h> #include<sys/wait.h> #include<pwd.h>#define SIZE 512 #define LEN 32 void getInput(char* arg[],char* input); int main() {printf("hello,It's me.\n");char* input=(char*)malloc(SIZE);//存儲用戶輸入的命令char* arg[10];//參數列表 1+9char exit_p[] = "exit"; //退出處理char exit_input[5];struct passwd* a = getpwuid(getuid());//獲得提示符char name[32];gethostname(name, 31);char current_dir[128];getcwd(current_dir, 127);while (1){printf("%s@%s:%s$ ",a->pw_name,name,current_dir);//打印提示符memset(input, 0, SIZE);//每次都清0fgets(input,SIZE-1,stdin);//獲得用戶輸入memcpy(exit_input, input, 4);//進行退出判斷,是否為"exit\n"if(input[4]=='\n'){exit_input[4]='\0';if (strcmp(exit_p, exit_input) == 0)break; //用戶輸入exit進行退出}getInput(arg, input);//將輸入字符串轉換為arg參數數組pid_t pid = fork();if (pid < 0)printf("error in fork().\n");else if (pid == 0){printf("my pid is %d,I will execute the task.\n\n", getpid());if (execvp(arg[0], arg) < 0)//執行用戶命令(如ls命令:不帶p的需要采用/bin/ls形式,帶p的會自動查找環境變量。){printf("error in execv().\n");exit(-1);}elseexit(0);}else{int status;int re = wait(&status);printf("\nchild process quit with status%d.\n", status);printf("child process pid=%d.\n", re);for (int i = 0; i < 10; i++)if (arg[i] != NULL)free(arg[i]);//每次都要釋放內存。}}free(input);return 0;} void getInput(char* arg[10], char* input) {for (int i = 0; i < 10; i++)arg[i] = NULL; //保證最后一個參數始終為NULLif (input[0] == '\n')return;int i = 0,flag = 1;//i 作為input的下標掃描輸入字符. flag 用于多個空格符的檢測以及是否使用 malloc()int j,k = -1;//k 作為參數的下標,最大為9. j為每個參數中字符的下標,最大為31while (input[i] != '\n'){if (input[i] == ' ')flag = 1;else{if(flag){flag = 0;k++;arg[k] = (char*)malloc(LEN);memset(arg[k], 0, LEN); //保證每個可用參數最后為'\0'j = 0;}arg[k][j++] = input[i];}i++;}return; }

功能

??????能夠實現 ls,ps,touch,rm等命令,不能實現 cd 命令,只能在當前目錄下進行操作。
??????輸入 exit 退出。

運行截圖

總結

以上是生活随笔為你收集整理的linux(1)- 简单的 shell 解释器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。