基于fork()与execvp()实现简易Shell:命令执行后程序退出问题求助
解决简易Shell循环运行的问题
嘿,我懂你现在的困扰——写的Shell执行一次命令就直接退出,没法循环接收输入对吧?核心问题就是你的代码缺少一个主循环结构,而且没处理exit指令的退出逻辑。我来给你一步步修改和解释:
完整修改后的代码
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <string.h> #define MAX_COMMAND_LENGTH 100 #define MAX_ARGS 10 int main() { char cadena[MAX_COMMAND_LENGTH]; char *argv[MAX_ARGS]; pid_t pid; // 主循环:持续运行直到输入exit或EOF while (1) { // 输出自定义Shell提示符 printf("myshell> "); fflush(stdout); // 强制刷新输出缓冲,确保提示符立即显示 // 读取用户输入 if (fgets(cadena, MAX_COMMAND_LENGTH, stdin) == NULL) { // 处理Ctrl+D这类EOF情况 printf("\n"); break; } // 去掉输入末尾的换行符(fgets会把回车读进来) cadena[strcspn(cadena, "\n")] = '\0'; // 判断是否输入exit,触发退出逻辑 if (strcmp(cadena, "exit") == 0) { printf("Exiting myshell...\n"); break; } // 将输入的命令行分割成execvp需要的参数数组 int arg_count = 0; argv[arg_count] = strtok(cadena, " "); while (argv[arg_count] != NULL && arg_count < MAX_ARGS - 1) { arg_count++; argv[arg_count] = strtok(NULL, " "); } argv[arg_count] = NULL; // execvp要求参数数组最后一个元素为NULL // 创建子进程执行命令 pid = fork(); if (pid == -1) { perror("fork failed"); continue; // 创建失败时跳过本次循环,继续等待下一次输入 } else if (pid == 0) { // 子进程:执行目标命令 execvp(argv[0], argv); // 如果execvp返回,说明命令执行失败 perror("execvp failed"); exit(EXIT_FAILURE); } else { // 父进程:等待子进程结束,避免产生僵尸进程 wait(NULL); } } return 0; }
关键修改点说明
- 主循环
while(1):这是让Shell持续运行的核心,只有遇到exit指令或EOF(比如按Ctrl+D)才会跳出循环终止程序。 exit指令判断:用strcmp对比输入字符串和"exit",匹配时直接跳出循环,结束Shell。- 输入处理优化:用
strcspn去掉fgets读取到的换行符,避免多余的换行影响命令执行。 - 命令参数分割:用
strtok把整行输入分割成argv数组,这是execvp要求的参数格式。 - 父进程等待子进程:通过
wait(NULL)让父进程(Shell)等待子进程(执行命令的进程)结束,既不会产生僵尸进程,也能保证命令执行完后才再次显示提示符。 - 提示符强制刷新:
fflush(stdout)解决了输出缓冲导致提示符延迟显示的问题。
额外小提示
如果输入的命令不存在,execvp会返回,子进程会打印错误信息后退出,父进程会继续循环等待下一次输入。后续你还可以扩展处理内置命令(比如cd,因为execvp无法改变父进程的工作目录,需要在父进程中单独处理)、管道等功能,但当前版本已经能满足你“循环运行直到输入exit”的基础需求。
内容的提问来源于stack exchange,提问作者TheAndreyx22
相关产品推荐
相关产品推荐

