Linux 進程控制(自用)

非阻塞調用waitpid
這樣父進程就不會阻塞,此時循環使用我們可以讓父進程執行其他任務而不是阻塞等待

進程程序替換
進程=PCB+加載到內存中的代碼和數據
替換就是完全替換當前進程的代碼段、數據段、堆和棧,保存當前的PCB

代碼指的是二進制代碼不是源碼!!!

  #include <unistd.h>extern char **environ;int execl(const char *pathname, const char *arg, .../* (char  *) NULL */);int execlp(const char *file, const char *arg, .../* (char  *) NULL */);int execle(const char *pathname, const char *arg, .../*, (char *) NULL, char *const envp[] */);int execv(const char *pathname, char *const argv[]);int execvp(const char *file, char *const argv[]);int execvpe(const char *file, char *const argv[],char *const envp[]);

pathname是要執行的可執行文件的完整路徑? /bin/ls
file程序名,不帶路徑在環境變量PATH查找

l就是list,以可變參數的形式傳遞"ls",“-l”,“NULL”
p就是會從環境變量查找,只要程序名即可
e就是環境變量數組
v就是vector以指針數組的形式傳遞

自定義shell的編寫

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <unordered_map>
#include <string>#define COMMAD_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;// 3.別名映射表
std::unordered_map<std::string, std::string> alias_list; // la對于ls -a// for test
char cwd[1024];
char cwdenv[1024];
char oldpwd[1024];
// 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;
}// 切換路徑時,環境變量表也要切換。因此我們要更新環境變量。
// 注意我們自定義shell的環境變量表繼承自shell
// 路徑先變,環境變量才變,調用系統調用
const char *GetPwd()
{const char *pwd = getcwd(cwd, sizeof(cwd));if (pwd){snprintf(cwdenv, sizeof(cwdenv), "PWD=%s", cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
}const char *GetOldPwd()
{return getenv("OLDPWD");
}
const char *GetHome()
{return getenv("HOME");
}void InitEnv()
{extern char **environ; // 頭文件#include <unistd.h>定義了這個,這里是聲明memset(g_env, 0, sizeof(g_env));// 本來從父進程繼承,現在直接從配置文件(操作系統)來// 1.獲取環境變量for (int i = 0; environ[i]; i++){// 申請空間// 別用sizeof,sizeof得到的是指針大小g_env[i] = (char *)malloc(strlen(environ[i]) + 1);strcpy(g_env[i], environ[i]);g_envs++;}g_env[g_envs] = NULL;// 2.導入環境變量// 增量修改for (int i = 0; g_env[i]; i++){putenv(g_env[i]);}// environ=g_env;完全重置
}// command 內建命令
bool Cd()
{memset(oldpwd, 0, sizeof(oldpwd));snprintf(oldpwd, sizeof(oldpwd), "OLDPWD=%s", GetPwd());putenv(oldpwd);if (g_argc == 1){std::string home = GetHome();if (home.empty())return true;chdir(home.c_str());}else{std::string where = g_argv[1];if (where == "-")chdir(GetOldPwd());else if (where == "~")chdir(GetHome());elsechdir(where.c_str());}return true;// cd argc = 1if (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; // echo執行完,退出碼應該是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;}}
}
// 防止自定義bash路徑名太長
/*std::string DirName(const char *pwd)
{
#define SLASH "/"std::string dir = pwd;if (dir == SLASH)return SLASH; // 只有根目錄直接返回auto pos = dir.rfind(SLASH);return dir.substr(pos + 1);
}*/
// 命令行提示符
void MakeCommandLine(char cmd_prompt[], int size)
{snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), GetPwd());
}
// 打印命令行提示符
void PrintCommandPrompt()
{char prompt[COMMAD_SIZE];MakeCommandLine(prompt, sizeof(prompt));std::cout << prompt;fflush(stdout);
}
bool GetCommandLine(char *out, int size)
{char *c = fgets(out, size, stdin);if (c == NULL)return false;out[strlen(out) - 1] = 0; // 清理\nif (strlen(out) == 0)return false; // 只輸入了/nreturn true;
}
// 3.命令行分析 "ls -a -l" 解析為 "ls" "-a" "-l"
bool CommandParse(char *commandline)
{
#define SEP " "g_argc = 0;g_argv[g_argc++] = strtok(commandline, SEP);while(g_argv[g_argc++] = strtok(nullptr, SEP));g_argc--;return g_argc > 0 ? true : false;
}void PrintArgv()
{for (int i = 0; g_argv[i]; i++){printf("argv[%d]->%s\n", i, g_argv[i]);}printf("argc: %d\n", g_argc);
}bool CheckAndExecBuiltin()
{std::string cmd = g_argv[0];if (cmd == "cd"){Cd();return true;}else if (cmd == "echo"){Echo();return true;}else if (cmd == "export")return true;else if (cmd == "alias")return true;return false;
}int Execute()
{pid_t id = fork();if (id == 0){// childexecvp(g_argv[0], g_argv);exit(1); // 一旦替換exit不會執行}// fatherint status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0)                        // 等待成功lastcode = WEXITSTATUS(status); // 獲取子進程退出碼return 0;
}int main()
{InitEnv();while (true) // 死循環{// 1.輸出命令行提示符PrintCommandPrompt();// 2.獲取用戶輸入的命令char commandline[COMMAD_SIZE];if (!GetCommandLine(commandline, COMMAD_SIZE))continue;// 3.命令行分析,并將分析后的命令行導入全面變量表中if (!CommandParse(commandline))continue;// 檢測是否是內建命令,若是直接調用然后continue,若不是則執行下面的if (CheckAndExecBuiltin())continue;;Execute();}return 0;
}

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

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

相關文章

Spring 微服務解決了單體架構的哪些痛點?

1. 部署困難 (Deployment Difficulty & Risk) 單體痛點: 整體部署: 對單體應用的任何微小修改&#xff08;哪怕只是一行代碼&#xff09;&#xff0c;都需要重新構建、測試和部署整個龐大的應用程序。部署頻率低: 由于部署過程復雜且風險高&#xff0c;發布周期通常很長&a…

面試題之高頻面試題

最近開始面試了&#xff0c;410面試了一家公司 針對自己薄弱的面試題庫&#xff0c;深入了解下&#xff0c;也應付下面試。在這里先祝愿大家在現有公司好好沉淀&#xff0c;定位好自己的目標&#xff0c;在自己的領域上發光發熱&#xff0c;在自己想要的領域上&#xff08;技術…

【MySQL】Read view存儲的機制,記錄可見分析

read view核心組成 1.1 事務id相關 creator_trx_id: 創建該read view的事務id 每開啟一個事務都會生成一個 ReadView&#xff0c;而 creator_trx_id 就是這個開啟的事務的 id。 m_ids: 創建read view時系統的活躍事務&#xff08;未提交的事務&#xff09;id集合 當前有哪些事…

【刷題Day20】TCP和UDP(淺)

TCP 和 UDP 有什么區別&#xff1f; TCP提供了可靠、面向連接的傳輸&#xff0c;適用于需要數據完整性和順序的場景。 UDP提供了更輕量、面向報文的傳輸&#xff0c;適用于實時性要求高的場景。 特性TCPUDP連接方式面向連接無連接可靠性提供可靠性&#xff0c;保證數據按順序…

Flink 內部通信底層原理

Flink 集群內部節點之間的通信是用 Akka 實現,比如 JobManager 和 TaskManager 之間的通信。而 operator 之間的數據傳輸是用 Netty 實現。 RPC 框架是 Flink 任務運行的基礎,Flink 整個 RPC 框架基于 Akka 實現。 一、相關概念 RPC(Remote Procedure Call) 概念 定義:…

企業級Kubernetes 1.28高可用集群離線部署全指南(含全組件配置)

企業級Kubernetes 1.28高可用集群離線部署全指南(含全組件配置) 摘要:本文手把手教學在無外網環境下部署生產級Kubernetes 1.28高可用集群,涵蓋ETCD集群、HAProxy+Keepalived負載均衡、Containerd運行時、Calico網絡插件及Kuboard可視化管理全流程。提供100年有效證書配置…

【中間件】redis使用

一、redis介紹 redis是一種NoSQL類型的數據庫&#xff0c;其數據存儲在內存中&#xff0c;因此其數據查詢效率很高&#xff0c;很快。常被用作數據緩存&#xff0c;分布式鎖 等。SpringBoot集成了Redis&#xff0c;可查看開發文檔Redis開發文檔。Redis有自己的可視化工具Redis …

C語言——函數遞歸與迭代

各位CSDN的uu們大家好呀&#xff0c;今天將會給大家帶來關于C語言的函數遞歸的知識&#xff0c;這一塊知識理解起來稍微會比較難&#xff0c;需要多花點時間。 話不多說&#xff0c;讓我們開始今天的內容吧&#xff01; 目錄 1.函數遞歸 1.1 什么是遞歸&#xff1f; 1.2 遞歸…

藏品館管理系統

藏品館管理系統 項目簡介 這是一個基于 PHP 開發的藏品館管理系統&#xff0c;實現了藏品管理、用戶管理等功能。 藏品館管理系統 系統架構 開發語言&#xff1a;PHP數據庫&#xff1a;MySQL前端框架&#xff1a;BootstrapJavaScript 庫&#xff1a;jQuery 目錄結構 book/…

centos停服 遷移centos7.3系統到新搭建的openEuler

背景 最近在做的事&#xff0c;簡單來講&#xff0c;就是一套系統差不多有10多臺虛擬機&#xff0c;都是centos系統&#xff0c;版本主要是7.3、7.6、7.9&#xff0c;現在centos停止維護了&#xff0c;轉為了centos stream&#xff0c;而centos stream的定位是&#xff1a;Red …

什么是 IDE?集成開發環境的功能與優勢

原文&#xff1a;什么是 IDE&#xff1f;集成開發環境的功能與優勢 | w3cschool筆記 &#xff08;注意&#xff1a;此為科普文章&#xff0c;請勿標記為付費文章&#xff01;且此文章并非我原創&#xff0c;不要標記為付費&#xff01;&#xff09; IDE 是什么&#xff1f; …

jenkins批量復制Job項目的shell腳本實現

背景 現在需要將“測試” 目錄中的所有job全部復制到 一個新目錄中 test2。可以結合jenkins提供的apilinux shell 進行實現。 測試目錄的實際文件夾名稱是 test。 腳本運行效果如下&#xff1a; [qdevsom5f-dev-hhyl shekk]$ ./copy_jenkins_job.sh 創建文件夾 test2 獲取源…

VisualSVN過期后的解決方法

作為一款不錯的源代碼管理軟件&#xff0c;svn還是有很多公司使用的。在vs中使用svn&#xff0c;大家一般用的都是VisualSVN插件。在30天試用期過后&#xff0c;它就不能被免費使用了。下面給大家講如何免費延長過期時間&#xff08;自定義天數&#xff0c;可以設定一個很大的值…

硬件工程師筆記——電子器件匯總大全

目錄 1、電阻 工作原理 歐姆定律 電阻的物理本質 一、限制電流 二、分壓作用 三、消耗電能&#xff08;將電能轉化為熱能&#xff09; 2、壓敏電阻 伏安特性 1. 過壓保護 2. 電壓調節 3. 浪涌吸收 4. 消噪與消火花 5. 高頻應用 3、電容 工作原理 &#xff08;…

[圖論]Kruskal

Kruskal 本質&#xff1a;貪心&#xff0c;對邊進行操作。存儲結構&#xff1a;邊集數組。適用對象&#xff1a;可為負權圖&#xff0c;可求最大生成樹。核心思想&#xff1a;最短的邊一定在最小生成樹(MST)上&#xff0c;對最短的邊進行貪心。算法流程&#xff1a;對全體邊集…

vulnhub five86系列靶機合集

five86 ~ VulnHubhttps://www.vulnhub.com/series/five86,272/ five86-1滲透過程 信息收集 # 主機發現 nmap 192.168.56.0/24 -Pn ? # 靶機全面掃描 nmap 192.168.56.131 -A -T4 目錄掃描 dirsearch -u http://192.168.56.131/ /robots.txt提示/ona。 /ona二層目錄掃描。 …

如何高效利用呼叫中心系統和AI語音機器人

要更好地使用呼叫中心系統和語音機器人&#xff0c;需要結合兩者的優勢&#xff0c;實現自動化、智能化、高效率的客戶服務與業務運營。以下是優化策略和具體實踐方法&#xff1a; 一、呼叫中心系統優化 1. 智能路由與IVR優化 智能ACD&#xff08;自動呼叫分配&#xff09; …

Nacos安裝及數據持久化

1.Nacos安裝及數據持久化 1.1下載nacos 下載地址&#xff1a;https://nacos.io/download/nacos-server/ 不用安裝&#xff0c;直接解壓縮即可。 1.2配置文件增加jdk環境和修改單機啟動standalone 找到bin目錄下的startup.cmd文件&#xff0c;添加以下語句(jdk路徑根據自己…

【牛客練習賽137 C】題解

比賽鏈接 C. 變化的數組(Easy Version) 題目大意 一個長度為 n n n 的非負數組 a a a&#xff0c;要求執行 k k k 次操作&#xff0c;每次操作如下&#xff1a; 有 1 2 \frac{1}{2} 21? 的概率令 a i ← a i ( a i ? m ) x , ? i ∈ [ 1 , n ] a_i \leftarrow a_…

Redis適用場景

Redis適用場景 一、加速緩存二、會話管理三、排行榜和計數器四、消息隊列五、實時分析六、分布式鎖七、地理位置數據八、限流九、數據共享十、簽到 一、加速緩存 Redis最常見的應用之一是作為緩存層&#xff0c;用于存儲頻繁訪問的數據&#xff0c;從而減輕數據庫的負載。 通過…