0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux實現(xiàn)簡易的Shell命令行解釋器

dyquk4xk2p3d ? 來源:入門小站 ? 作者:入門小站 ? 2023-03-30 10:00 ? 次閱讀

一、前言

來制作一個簡易的 [Shell 命令]行解釋器。

首先這是與 Shell 的互動::

ae1c7a54-ce8a-11ed-bfe3-dac502259ad0.png

用下圖的[時間軸]來表示事件的發(fā)生次序。其中時間從> > 左向右。shell 由標識為 sh 的方塊代表,它隨著時間的流逝從左向右移動。shell 從用戶讀入字符串 "ls"。shell 建立一個新的進程,然后在那個進程中運行 ls 程序并等待那個進程結束。

ae3edf4a-ce8a-11ed-bfe3-dac502259ad0.png

然后 shell 讀取新的一行輸入,建立一個新的進程,在這個進程中運行程序 并等待這個進程結束。所以要寫一個 shell,需要循環(huán)以下過程:

1. 獲取命令行

2. 解析命令行

3. 建立一個子進程(fork)

4. 替換子進程(execvp)

5. 父進程等待子進程退出(wait)

二、準備工作

1.輸出提示符

ae709f44-ce8a-11ed-bfe3-dac502259ad0.png

這里的提示字符為用戶名 @主機名 當前路徑# 直接打印出來作為提示所用

printf("用戶名@主機名當前路徑#");

這里沒有 n,會有緩沖區(qū)的問題,類似于我們之前所說的進度條所遇到的問題,可以用 fflush(stdout) 刷新緩沖區(qū)。

2. 輸入和獲取命令

輸入

我們需要輸入一連串命令,其中可能出現(xiàn)空格,所以不能使用 gets 函數(shù),需要用到 fgets 函數(shù),同時,可以定義一個 lineCommand[NUM] 數(shù)組

#defineNUM1024
charlineCommand[NUM];
char*s=fgets(lineCommand,sizeof(lineCommand)-1,stdin);
assert(s!=NULL);

但是打印的時候卻多換了一行,這是我們把 n 也讀取到了,直接進行處理即可, 清除最后一個 n

lineCommand[strlen(lineCommand)-1]=0;

可以通過打印看看效果和測試是否有 BUG

printf("test:%s
",lineCommand);
ae85b9c4-ce8a-11ed-bfe3-dac502259ad0.png

獲取

輸入之后,我們自然需要去進行獲取,我們需要分割命令行,這個地方用 strtok。把字符串切割成若干個子串:
strtok: 第一次直接傳遞參數(shù),第二次則必須傳 NULL。且在最終 strtok 會返回 NULL。

ae99dc06-ce8a-11ed-bfe3-dac502259ad0.pngaec2e524-ce8a-11ed-bfe3-dac502259ad0.png

3.shell 運行原理

同時,在理解一下 shell 的運行原理:shell 內部提取命令行做分析,然后調用 exec. shell 執(zhí)行命令必須通過創(chuàng)建子進程,如果不創(chuàng)建子進程會把我們所有的 shell 全部替換,所以執(zhí)行命令時一般磁盤上的程序必須創(chuàng)建子進程。

4. 內建命令

我們在運行自己寫的 shell 的時候,發(fā)現(xiàn)輸入 cd … 輸入 cd path 等命令時發(fā)現(xiàn)路徑并沒有改變!

aee97ca2-ce8a-11ed-bfe3-dac502259ad0.png

沒有發(fā)生改變是因為自己寫的 shell 執(zhí)行很多命令都要 fork() 創(chuàng)建子進程,讓子進程執(zhí)行的 cd,子進程有自己的工作目錄,所以更改的子進程的目錄,子進程執(zhí)行完畢,繼續(xù)用的是父進程,既 shell,并沒有影響父進程,所以并沒有改變。

對于 cd, 我們可以采用內建命令:不需要創(chuàng)建子進程執(zhí)行,讓 shell 自己執(zhí)行命令,稱為內建命令。本質就是執(zhí)行系統(tǒng)接口,我們可以調用一個系統(tǒng)接口 chdir,可解決上述問題:

aefa5928-ce8a-11ed-bfe3-dac502259ad0.png
af185b26-ce8a-11ed-bfe3-dac502259ad0.png

5. 替換

采用 execvp 進行替換進程

pid_tid=fork();
assert(id!=-1);
if(id==0)
{
execvp(myargv[0],myargv);
exit(1);
}

三、整體代碼

 #include
#include
#include
#include
#include
#include
#include
#defineNUM1024
#defineOPT_NUM64
charlineCommand[NUM];
char*myargv[OPT_NUM];//指針數(shù)組
intlastcode=0;
intlastsig=0;
intmain()
{
while(1)
{
//1.輸出提示符
printf("lj@VM-8-2-centos當前路徑#");
fflush(stdout);
//2.獲取用戶輸入的命令,輸入的時候,用戶最后還輸入了

char*s=fgets(lineCommand,sizeof(lineCommand)-1,stdin);
assert(s!=NULL);
(void)s;//避免Linux認為s變量未使用,導致警告
//清除最后一個
;例如:abcd

lineCommand[strlen(lineCommand)-1]=0;
//printf("test:%s
",lineCommand);
//"ls-a-l-i"-->字符串分割-->"ls""-a""-l""-i"
myargv[0]=strtok(lineCommand,"");
inti=1;
if(myargv[0]!=NULL&&(strcmp(myargv[0],"ls")==0))
{
myargv[i++]=(char*)"--color=auto";
}
//如果沒有子串了,strtok會返回NULL,即myargv[end]=NULL
while(myargv[i++]=strtok(NULL,""));
//如果是cd命令,不需要創(chuàng)建子進程,讓shell自己執(zhí)行對應的命令,本質就是執(zhí)行系統(tǒng)接口
//像這種不需要讓我們的子進程來執(zhí)行,而是讓shell自己執(zhí)行的命令—內建命令
//其中echo是一個自建命令
if(myargv[0]!=NULL&&(strcmp(myargv[0],"cd")==0))
{
if(myargv[1]!=NULL)chdir(myargv[1]);
continue;
}
if(myargv[0]!=NULL&&myargv[1]!=NULL&&(strcmp(myargv[0],"echo")==0))
{
if(strcmp(myargv[1],"$?")==0)
{
printf("%d,%d
",lastcode,lastsig);
}
else
{
printf("%s
",myargv[i]);
}
continue;
}
//利用條件編譯測試是否成功
#ifdefDEBUG
for(inti=0;myargv[i];++i)
{
printf("myargv[%d]:%s
",i,myargv[i]);
}
#endif
//執(zhí)行命令
pid_tid=fork();
assert(id!=-1);
if(id==0)
{
execvp(myargv[0],myargv);
exit(1);
}
intstatus=0;
pid_tret=waitpid(id,&status,0);
assert(ret>0);
(void)ret;
lastcode=(status>>8)&0xFF;
lastsig=status&0x7F;
}
return0;
}
af335782-ce8a-11ed-bfe3-dac502259ad0.png

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11171

    瀏覽量

    208472
  • 命令行
    +關注

    關注

    0

    文章

    77

    瀏覽量

    10369
  • Shell
    +關注

    關注

    1

    文章

    361

    瀏覽量

    23234
  • 進程
    +關注

    關注

    0

    文章

    200

    瀏覽量

    13933
  • 解釋器
    +關注

    關注

    0

    文章

    103

    瀏覽量

    6479

原文標題:Linux 實現(xiàn)簡易的 Shell 命令行解釋器

文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    在STM32實現(xiàn)命令行

    工作中的開發(fā)環(huán)境都是基于linux命令行交互,作為命令行的重度使用者,玩單片機也要使用命令行工具,百度了一些命令行工具,有幾個不錯的開源 c
    發(fā)表于 12-09 11:32 ?2189次閱讀

    Linux圖形界面的原理與構成和Linux命令行和vi編輯的使用手冊

    本文檔的主要內容詳細介紹的是Linux基礎教案主要內容是:(1) 了解Linux圖形界面的原理與構成;(2)掌握Linux命令行操作,包括:命令行
    發(fā)表于 10-16 14:49 ?6次下載
    <b class='flag-5'>Linux</b>圖形界面的原理與構成和<b class='flag-5'>Linux</b><b class='flag-5'>命令行</b>和vi編輯<b class='flag-5'>器</b>的使用手冊

    Linux桌面系統(tǒng)初級教程之Shell命令行操作的資料概述

    Linux shell指的是一種程序,有了它,用戶就能通過鍵盤輸入指令來操作計算機了。Shell會執(zhí)行用戶輸入的命令,并且在顯示上顯示執(zhí)行
    發(fā)表于 11-09 17:42 ?18次下載
    <b class='flag-5'>Linux</b>桌面系統(tǒng)初級教程之<b class='flag-5'>Shell</b><b class='flag-5'>命令行</b>操作的資料概述

    Linux 命令行教程好書推薦

    今天跟大家推薦個 Linux 命令行教程:《The Linux Command Line》,中文譯名:《Linux 命令行大全》。 該書作者
    的頭像 發(fā)表于 02-14 09:25 ?1417次閱讀

    mini shell命令行調試工具(單片機、c語言)

    @mini shell命令行調試工具介紹Mini shell 命令行調試工具(單片機、c語言)Mini shell是一個特別適合低內存的單片
    發(fā)表于 11-29 10:21 ?9次下載
    mini <b class='flag-5'>shell</b><b class='flag-5'>命令行</b>調試工具(單片機、c語言)

    Shell命令行解釋簡介

    Shell 是一個命令行解釋,Shell 為用戶提供了與設備進行命令行交互的方式,用戶通過串口
    的頭像 發(fā)表于 08-19 17:20 ?3092次閱讀

    Linux命令行shell腳本編寫

    Linux命令行shell腳本編寫
    發(fā)表于 01-11 16:50 ?4次下載

    如何在Linux命令行中運行Python腳本

    Python 是一種高級編程語言,被廣泛應用于數(shù)據(jù)科學、機器學習、Web 開發(fā)等領域。在 Linux 操作系統(tǒng)中,Python 是一個默認安裝的解釋,用戶可以通過命令行界面(CLI)
    的頭像 發(fā)表于 05-12 14:49 ?1618次閱讀

    單片機上如何做shell命令行交互

    做個shell命令行交互?答案當然是可以的,在網(wǎng)上類似的文章和代碼一搜一籮筐, 基本原理: 監(jiān)測用戶的輸入,然后到一個命令查找表里過濾是否可以找到該命令,如果可以則調用對應的處理函數(shù),
    的頭像 發(fā)表于 11-01 15:16 ?1192次閱讀

    shell命令linux命令一樣嗎

    Shell命令Linux命令并不完全一樣。 首先,Shell是一種命令行
    的頭像 發(fā)表于 11-08 10:51 ?2594次閱讀

    linux命令shell編程有什么聯(lián)系

    Linux命令Shell編程之間存在密切的聯(lián)系。 首先,ShellLinux命令行下的
    的頭像 發(fā)表于 11-08 10:53 ?838次閱讀

    linux命令行shell編程實戰(zhàn)

    Linux命令行Shell編程實戰(zhàn)主要涉及以下內容: Linux命令行基礎:學習Linux
    的頭像 發(fā)表于 11-08 10:57 ?677次閱讀

    linux虛擬機怎么調出命令行

    Linux虛擬機中調出命令行界面,可以通過以下步驟實現(xiàn): 打開虛擬機,進入到Linux系統(tǒng)。 在桌面或應用菜單中找到終端或命令行圖標,點擊
    的頭像 發(fā)表于 11-08 11:28 ?2787次閱讀

    linux切換到命令行模式

    Linux中,可以通過以下步驟切換到命令行模式: 打開終端??梢栽趹貌藛沃姓业浇K端或命令行終端。 在終端中輸入命令“exit”或“l(fā)ogout”,然后按回車鍵。 系統(tǒng)會提示您輸入管
    的頭像 發(fā)表于 11-13 16:47 ?1606次閱讀

    linux命令行運行步驟

    運行Linux命令行涉及以下步驟: 打開終端 在Linux系統(tǒng)中,打開命令行界面的方式有多種,最常見的是打開終端應用程序??梢栽趹贸绦虿藛沃姓业浇K端,點擊打開。 熟悉
    的頭像 發(fā)表于 11-17 10:18 ?703次閱讀