news 2026/4/22 23:08:52

【Linux】进程控制(4)自主shell命令行解释器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Linux】进程控制(4)自主shell命令行解释器

【Linux】进程控制(4)自主shell命令行解释器

这一部分的目标是:自己动手写一个极简的 shell,通过这个过程把之前学过的进程控制知识(fork/exec/wait/signal/管道/重定向等)串联起来。

目标 shell 的功能范围(极简版)

  • 显示提示符(如myshell$
  • 读取一行用户输入
  • 支持最基本的命令执行(不带参数也可以先支持)
  • 支持带参数的命令(空格分隔)
  • 支持后台运行(命令末尾有&
  • 支持前台命令的 wait
  • 支持 exit / quit 退出
  • (可选扩展)支持管道|、重定向>>><&&||

实现思路总览

while (true) { 打印提示符 读取整行输入 → line 如果 line 为空 或 是 exit/quit → break 解析 line → 切分出命令 + 参数数组 argv[] → 判断是否有 & (后台) if (是内置命令,如 cd exit) { 直接在当前进程执行 } else { pid = fork() if (pid == 0) { // 子进程 execvp(命令, argv) perror("exec失败"); exit(1); } else { // 父进程(shell) if (不是后台) { waitpid(pid, &status, 0); } else { printf("[后台任务] pid = %d\n", pid); // 可以选择不 wait,等它自己结束或用 waitpid(-1,...) 回收 } } } }

极简版代码(推荐先实现这个)

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/wait.h>#include<errno.h>#defineMAX_LINE1024#defineMAX_ARGS64intmain(void){charline[MAX_LINE];char*argv[MAX_ARGS];charprompt[]="myshell$ ";while(1){printf("%s",prompt);fflush(stdout);// 读取整行if(!fgets(line,MAX_LINE,stdin)){break;// ctrl+D}// 去掉末尾换行line[strcspn(line,"\n")]=0;// 空行直接继续if(strlen(line)==0)continue;// 退出命令if(strcmp(line,"exit")==0||strcmp(line,"quit")==0){break;}// 解析参数intargc=0;char*token=strtok(line," \t");intbackground=0;while(token){if(strcmp(token,"&")==0){background=1;break;// & 后面不再解析}argv[argc++]=token;token=strtok(NULL," \t");}argv[argc]=NULL;if(argc==0)continue;// 内置命令(先简单处理 exit/cd)if(strcmp(argv[0],"cd")==0){if(argc<2){fprintf(stderr,"cd: 缺少参数\n");}elseif(chdir(argv[1])!=0){perror("chdir");}continue;}// fork + execpid_tpid=fork();if(pid<0){perror("fork");continue;}if(pid==0){// 子进程execvp(argv[0],argv);// 走到这里说明 exec 失败fprintf(stderr,"命令 '%s' 执行失败: %s\n",argv[0],strerror(errno));exit(127);}// 父进程if(!background){intstatus;waitpid(pid,&status,0);}else{printf("[后台作业] pid = %d\n",pid);// 可以不 wait,让它成为孤儿进程,由 init 回收// 或者后续用 waitpid(-1, ...) 非阻塞回收}}printf("\nbye~\n");return0;}

编译 & 运行

gcc -o myshell myshell.c ./myshell

然后就可以输入:

myshell$ ls -l myshell$ sleep 10 & myshell$ pwd myshell$ cd /tmp myshell$ exit

进阶功能(按难度递增)

优先级功能关键实现点难度
★☆☆支持管道 `cmd1cmd2`fork 两次 + pipe() + dup2
★★☆支持重定向> >> <解析 > >> <,用 open() + dup2★★★
★★☆回收所有后台进程(waitpid)非阻塞 waitpid(-1, &status, WNOHANG) 循环★★
★★★支持&&``
★★★实现!历史命令保存历史链表,按 !n 执行★★★
★★★★支持环境变量展开$HOME解析 $ 开头的词,用 getenv() 替换★★★★
★★★★支持通配符 * ?用 glob() 或自己实现匹配★★★★★

推荐进阶顺序(比较实用)

  1. 先把上面的极简版跑通
  2. 加上后台进程的非阻塞回收(每轮循环末尾试一次 waitpid(-1, …, WNOHANG))
  3. 实现最简单的重定向(只支持><
  4. 再实现单级管道(最有成就感)

小提示

  • 解析命令行时建议用strtok_r()(可重入版本)更安全
  • 处理输入时考虑连续空格、tab、行首尾空格
  • execvp() 失败时退出码常用 127(command not found)
  • 后台进程结束时如果不回收,会出现僵尸进程(zombie)

如果你现在想继续做这个项目,可以告诉我你想先实现哪个功能(管道、重定向、后台回收、历史命令……),我可以给你对应的核心代码片段和注意事项。

祝你写出一个属于自己的 shell~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:36:52

软件测试从业者公众号内容热度解析与优化策略

在微信公众号生态中&#xff0c;内容热度直接决定技术传播效果。对于软件测试从业者&#xff0c;精准识别高热度主题&#xff08;如自动化测试框架或AI应用&#xff09;能显著提升用户粘性和行业影响力。本报告结合数据分析指标、工具应用和行业案例&#xff0c;提供可落地的优…

作者头像 李华
网站建设 2026/4/18 2:55:14

计算机毕业设计之基于Spring boot食品安全信息管理系统

食品安全信息管理系统设计的目的是为用户提供食品信息、科普专栏、食品检测、检测结果、交流论坛等方面的平台。 与PC端应用程序相比&#xff0c;食品安全信息管理系统的设计主要面向于用户&#xff0c;旨在为管理员和用户提供一个食品安全信息管理系统。用户可以通过APP及时查…

作者头像 李华
网站建设 2026/4/22 18:49:33

计算机毕业设计之基于SSM的社区疫情管理系统的设计与实现

社区疫情管理系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的java进行编写&#xff0c;JSP技术&#xff0c;使用了SSM框架。该系统从两个对象&#xff1a;由管理员和居民来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对居…

作者头像 李华
网站建设 2026/4/18 9:35:43

金属基板常见失效模式分析与可靠性设计改进

在金属基板量产售后与失效分析案例中&#xff0c;高频失效类型&#xff1a;绝缘层击穿、铜箔剥离、基板翘曲变形、热疲劳开裂、焊接不良。这些问题 80% 源于设计阶段参数不合理、材料选型错误、工艺适配缺失&#xff0c;而非生产加工瑕疵。本文系统解析主流失效模式、成因&…

作者头像 李华
网站建设 2026/4/18 3:39:44

云服务器ECS-高性能弹性计算服务-99.995%可用性保障

云服务器ECS概述云服务器ECS&#xff08;Elastic Compute Service&#xff09;是一种高性能、可弹性伸缩的云计算服务&#xff0c;提供安全可靠的计算能力。用户可根据需求灵活选择CPU、内存、带宽等配置&#xff0c;支持多种操作系统和应用场景。ECS具备99.995%的高可用性保障…

作者头像 李华