Linux:簡單自定義shell

1.實現原理

考慮下?這個與shell典型的互動:

[root@localhost epoll]# ls
client.cpp readme.md server.cpp utility.h
[root@localhost epoll]# ps
PID TTY TIME CMD
3451 pts/0 00:00:00 bash
3514 pts/0 00:00:00 ps
?下圖的時間軸來表?事件的發?次序。其中時間從左向右。shell由標識為sh的?塊代表,它隨著時間的流逝從左向右移動。shell從??讀?字符串"ls"。shell建??個新的進程,然后在那個進程中運?ls程序并等待那個進程結束。

?

然后shell讀取新的??輸?,建??個新的進程,在這個進程中運?程序 并等待這個進程結束。
所以要寫?個shell,需要循環以下過程:
  1. 獲取命令?
  2. 解析命令?
  3. 建??個?進程(fork)
  4. 替換?進程(execvp)
  5. ?進程等待?進程退出(wait)

2.實現代碼

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>#define COMMAND_SIZE 1024
#define FORMAT "[%s@%s %s]"//shell定義的全局數據//1.命令行參數表
#define MAXARGC 128
char* g_argv[MAXARGC];
int g_argc = 0;//2.環境變量表
#define MAX_ENVS 100
char* g_env[MAX_ENVS];
int g_envs = 0;char cwd[1024];
char cwdenv[2048];//last exit code
int lastcode = 0;const char* GetUserName()
{const char* name = getenv("USER");return name == NULL ? "None" : name;
}const char* GetHostName()
{const char* hostname = getenv("HOSTNAME");return hostname == NULL ? "None" : hostname;
}const char* GetPwd()
{const char* pwd = getcwd(cwd, sizeof(cwd));if (pwd != NULL){snprintf(cwdenv, sizeof(cwdenv), "PWD=%s", cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
}const char* GetHome()
{const char* home = getenv("HOME");return home == NULL ? "" : home;
}void InitEnv()
{extern char** environ;memset(g_env, 0, sizeof(g_env));g_envs = 0;//從配置文件中獲取環境變量for (int i = 0; environ[i]; i++){g_env[i] = (char*)malloc((strlen(environ[i]) + 1));strcpy(g_env[i], environ[i]);g_envs++;}//測試g_env[g_envs++] = (char*)"HAHA=for_test";g_env[g_envs] = NULL;//導成環境變量for (int i = 0; g_env[i]; i++){putenv(g_env[i]);}environ = g_env;
}bool Cd()
{if (g_argc == 1){std::string home = GetHome();if (home.empty())return true;chdir(home.c_str());}else{std::string where = g_argv[1];// cd - / cd ~if (where == "-"){// Todu}else if (where == "~"){// Todu}else{chdir(where.c_str());}}return true;
}void Echo()
{if (g_argc == 2){std::string opt = g_argv[1];if (opt == "$?"){std::cout << lastcode << std::endl;lastcode = 0;}else if (opt[0] == '$'){std::string env_name = opt.substr(1);const char* env_value = getenv(env_name.c_str());if (env_value)std::cout << env_value << std::endl;}else{std::cout << opt << std::endl;}}
}std::string DirName(const char* pwd)
{
#define SLASH "/"std::string dir = pwd;if (dir == SLASH)return SLASH;auto pos = dir.rfind(SLASH);if (pos == std::string::npos)return "BUG?";return dir.substr(pos + 1);
}void MakeCommandLine(char cmd_prompt[], int size)
{snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), DirName(GetPwd()).c_str());
}void PrintCommandPrompt()
{char prompt[COMMAND_SIZE];MakeCommandLine(prompt, sizeof(prompt));printf("%s", prompt);fflush(stdout);
}bool GetCommandLine(char* out, int size)
{//ls -a -l ->"ls -a -l"字符串char* c = fgets(out, size, stdin);if (c == NULL)return false;//fgets失敗out[strlen(out) - 1] = 0;//清理\nif (strlen(out) == 0)return false;//如只輸入\nreturn true;
}bool CommandParse(char* commandline)
{
#define SEP " "g_argc = 0;//命令行分析"ls -a -l"->"ls" "-a" "-l"  g_argv[g_argc++] = strtok(commandline, SEP);while ((bool)(g_argv[g_argc++] = strtok(nullptr, SEP)));g_argc--;return g_argc > 0 ? true : false;}bool CheckAndExecBuildin()
{std::string cmd = g_argv[0];if (cmd == "cd"){Cd();return true;}else if (cmd == "echo"){Echo();return true;}//else if(cmd == "export")//else if(cmd == "alias")//...return false;
}int Execute()
{pid_t id = fork();if (id == 0){execvp(g_argv[0], g_argv);exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){lastcode = WEXITSTATUS(status);}return 0;
}int main()
{// shell 啟動的時候,從系統中獲取環境變量// 我們的環境變量信息應該從父shell統一來InitEnv();while (true){//1.輸出命令行提示符PrintCommandPrompt();//2.輸入用戶輸入的命令char commandline[COMMAND_SIZE];if (!GetCommandLine(commandline, sizeof(commandline)))continue;//3.命令行分析"ls -a -l"->"ls" "-a" "-l"if (!CommandParse(commandline))continue;//4.檢測并處理內建命令if (CheckAndExecBuildin())continue;//5.執行命令Execute();}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76837.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76837.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76837.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PLSQL語法入門--PL/SQL 基礎詳解

PL/SQL 基礎詳解 PL/SQL&#xff08;Procedural Language for SQL&#xff09;是 Oracle 數據庫中的一種過程式語言&#xff0c;它擴展了 SQL 的功能&#xff0c;允許開發者編寫復雜的程序邏輯。 一、匿名塊 解釋 匿名塊是 PL/SQL 的基本執行單位&#xff0c;它是一段獨立的…

Oracle--用戶管理

前言&#xff1a;本博客僅作記錄學習使用&#xff0c;部分圖片出自網絡&#xff0c;如有侵犯您的權益&#xff0c;請聯系刪除 用戶管理在 Oracle 數據庫中至關重要。一個服務器通常只運行一個 Oracle 實例&#xff0c;而一個 Oracle 用戶代表一個用戶群&#xff0c;他們通過該用…

UOS+N 卡 + CUDA 環境下 X86 架構 DeepSeek 基于 vLLM 部署與 Dify 平臺搭建指南

一、文檔說明 本文檔是一份關于 DeepSeek 在X86架構下通vLLM工具部署的操作指南&#xff0c;主要面向需要在UOSN卡CUDA環境中部署DeepSeek的技術人員&#xff0c;旨在指導文檔使用者完成從 Python 環境升級、vLLM 庫安裝、模型部署到 Dify 平臺搭建的全流程操作。 二、安裝Pyt…

操作系統之shell實現(下)

&#x1f31f; 各位看官好&#xff0c;我是maomi_9526&#xff01; &#x1f30d; 種一棵樹最好是十年前&#xff0c;其次是現在&#xff01; &#x1f680; 今天來學習C語言的相關知識。 &#x1f44d; 如果覺得這篇文章有幫助&#xff0c;歡迎您一鍵三連&#xff0c;分享給更…

Spark,流量統計案例

提前創好一個文件夾分為四個類 FlowBean中的代碼內容為&#xff1a;package org.example.flow; import org.apache.hadoop.io.Writable; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; //hadoop 序列化 //三個屬性&#xff1a;手機…

下載油管視頻 - yt-dlp

文章目錄 1. yt-dlp與you-get介紹1.1 主要功能對比1.2 使用場景1.3 安裝 2. 基本命令介紹2.1 默認下載視頻2.2 指定畫質和格式規則2.3 下載播放列表2.4 備注 3. 參考資料 之前只使用you-get下載b站視頻&#xff0c;當時了解you-get也可下載油管視頻&#xff0c;但之前無此需求&…

基于javaweb的SSM+Maven教材管理系統設計與實現(源碼+文檔+部署講解)

技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、小程序、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;免費功能設計、開題報告、任務書、中期檢查PPT、系統功能實現、代碼編寫、論文編寫和輔導、論文…

VS2022+QT環境配置及基本操作

參考文章 2025最新&#xff01;Visual Studio 2022 QT6.7 環境配置全攻略&#xff1a;一鍵搞定安裝與亂碼問題&#xff0c;開發效率翻倍&#xff01;&#xff08;全網最詳細教程&#xff0c;手把手教你搭建完美開發環境&#xff01;&#xff09;_vs2022 qt-CSDN博客 下載QT …

使用percona-toolkit同步mysql表數據

背景 做了主備mysql的配置以后&#xff0c;可能因為切換過程造成不一致的情況&#xff0c;這個時候可以處理的方式是全量導入再導出&#xff0c;這個有個問題就是操作的數據太多了 我們只需要數據補全同步即可 mysql的同步是基于binlog的&#xff0c;如果沒有記錄的部分的數據…

MDG 實現后端主數據變更后快照自動刷新的相關設置

文章目錄 前言實現過程BGRFC期初配置&#xff08;可選&#xff09;設置 MDG快照 BGRFC維護BP出站功能模塊 監控 前言 眾所周知&#xff0c;在MDG變更請求創建的同時&#xff0c;所有reuse模型實體對應的快照snapshot數據都會記錄下來。隨后在CR中&#xff0c;用戶可以修改這些…

重裝系統 之 Dell戴爾服務器 PowerEdge R750xs + window server2012r2 || 2016

因要求需要給新服務器裝個 win server2012或者2016系統 XXX使用U盤制作PE系統U盤安裝系統不行&#xff0c;適合普通win8&#xff0c;win10&#xff0c;win11U盤制作PE系統U盤安裝win10系統教程U盤制作PE系統U盤安裝win10系統教程https://mp.weixin.qq.com/s/t0W8aNJaHPAU8T78nh…

基于Spring Security 6的OAuth2 系列之二十六 - 終章

之所以想寫這一系列&#xff0c;是因為之前工作過程中使用Spring Security OAuth2搭建了網關和授權服務器&#xff0c;但當時基于spring-boot 2.3.x&#xff0c;其默認的Spring Security是5.3.x。之后新項目升級到了spring-boot 3.3.0&#xff0c;結果一看Spring Security也升級…

一鍵配置多用戶VNC遠程桌面:自動化腳本詳解

在當今遠程工作盛行的時代,高效且安全地管理多用戶遠程桌面訪問變得至關重要。本文將介紹一個強大的自動化腳本,該腳本能夠快速創建用戶并配置VNC遠程桌面環境,大大簡化了系統管理員的工作。 一、背景介紹 在Linux系統中,手動配置VNC服務器通常需要執行多個步驟,包括創建…

IOT項目——雙軸追光系統

雙軸太陽能追光系統 - ESP32實現 系統概述 這個系統使用&#xff1a; ESP32開發板2個舵機&#xff08;水平方向和垂直方向&#xff09;4個光敏電阻&#xff08;用于檢測光照方向&#xff09;適當的電阻&#xff08;用于光敏電阻分壓&#xff09; 接線示意圖 --------------…

Maven集成模塊打包使用

文章目錄 1.問題思考&#xff08;如何對集成模塊進行打包&#xff09;2.問題解決 &#xff08;如何對集成模塊進行打包&#xff09;3.使用者使用該jar包(jar包安裝本地倉庫和使用) 1.問題思考&#xff08;如何對集成模塊進行打包&#xff09; 思考&#xff1a;假設有這么一個場…

OpenVINO教程(二):圖片目標檢測推理應用

YOLO模型物體檢測 下面是一個簡單的python程序,他的功能是使用yolo11n模型對coco_bike.jpg照片進行檢測,并顯示檢測結果 代碼步驟如下: coco_bike.jpg照片加載yolo模型使用模型進行detect推理顯示推理結果 下面是完整的代碼 from pathlib import Pathimport urllib.request…

聚類算法(K-means、DBSCAN)

聚類算法 K-means 算法 算法原理 K-means 是一種基于類內距離最小化的劃分式聚類算法&#xff0c;其核心思想是通過迭代優化將數據劃分為 K 個簇。目標函數為最小化平方誤差&#xff08;SSE&#xff09;&#xff1a; S S E ∑ i 1 K ∑ x ∈ C i ∣ ∣ x ? μ i ∣ ∣ 2…

Oracle在ERP市場擊敗SAP

2024年&#xff0c;甲骨文&#xff08;Oracle&#xff09;以87億美元的ERP收入和6.63%的市場份額&#xff0c;首次超越SAP&#xff0c;成為全球最大的ERP應用軟件供應商&#xff0c;結束了SAP自上世紀80年代以來在該領域的長期霸主地位。據APPS RUN THE WORLD的市場調研&#x…

嵌入式面試高頻筆試題目解析

一、基礎概念與 C 語言核心題 1. 指針與內存操作 典型題目: char str[] = "hello"; char *ptr = "world"; str[0] = H; // 合法嗎? ptr[0] = W; // 合法嗎?為什么?解析: str 是棧上數組,可修改內容,str[0]=H 合法。ptr 指向常量字符串區,修改會…

【Python】Selenium切換網頁的標簽頁的寫法(全!!!)

在使用selenium做網站爬取測試的時候&#xff0c;我們經常會遇到一些需要點擊的元素&#xff0c;才能點擊到我們想要進入的頁面&#xff0c; 于是我們就要模擬 不斷地 點點點擊 鼠標的樣子。 這個時候網頁上就會有很多的標簽頁&#xff0c;你的瀏覽器網頁標簽欄 be like: 那…