C语言execvp用法疑问:执行ls无响应,代码遗漏了什么?
问题分析与修复方案
你的代码存在多个关键问题,导致执行命令无响应或行为异常,逐个梳理如下:
- 未初始化的指针触发未定义行为:
char *myCmd;是野指针,未分配有效内存就用scanf("%s", myCmd)写入,会直接破坏内存,程序行为完全不可控。必须给myCmd分配足够的内存空间。 - fork位置错误:
fork()放在while循环外,只会创建一次子进程。子进程执行execvp后就会退出,后续循环里的pid指向的是已退出的子进程,无法再执行新命令。必须把fork()移到每次处理命令的逻辑里。 - 参数数组未以NULL结尾:
execvp要求传入的参数数组最后一个元素必须是NULL,否则无法正确识别参数列表,会导致执行失败。 - scanf无法读取带空格的命令:
scanf("%s")会在空格处停止读取,无法处理ls -l这类带参数的命令,应该用fgets读取整行输入。 - 后台命令处理逻辑错误:原代码中
strcmp(tokens[i-1], "&")的判断逻辑反了(strcmp返回0才表示相等),而且没有把&从参数数组中移除,会导致execvp把&当作命令的一部分执行。 - 子进程执行失败未退出:
execvp执行失败后应该立即退出子进程,否则子进程会进入父进程的循环,导致逻辑混乱。 - 缺少退出命令处理:没有设置
should_run为0的逻辑,程序无法正常退出。
修正后的代码
#include <stdio.h> #include <unistd.h> #include <string.h> #include <wait.h> #include <stdlib.h> #define MAX_LINE 80 /* Maximum length of a command */ int main(void) { char myCmd[MAX_LINE]; /* 分配足够内存存储命令行输入 */ int should_run = 1; /* 控制程序退出的标志 */ pid_t pid; char *tokens[MAX_LINE/2 + 1]; while (should_run) { printf("osh>"); fflush(stdout); // 读取整行输入并处理换行符 if (fgets(myCmd, MAX_LINE, stdin) == NULL) { break; } myCmd[strcspn(myCmd, "\n")] = '\0'; // 去掉末尾的换行符 // 处理退出命令 if (strcmp(myCmd, "exit") == 0) { should_run = 0; continue; } int i = 0; char *token = strtok(myCmd, " "); while (token != NULL) { tokens[i] = token; i++; token = strtok(NULL, " "); } int is_background = 0; // 判断是否是后台命令 if (i > 0 && strcmp(tokens[i-1], "&") == 0) { is_background = 1; tokens[i-1] = NULL; // 移除&,让参数数组正确结尾 } else { tokens[i] = NULL; // 参数数组必须以NULL结尾 } pid = fork(); // 每次处理命令都创建新的子进程 if (pid < 0) { perror("Fork Failed"); exit(EXIT_FAILURE); } else if (pid == 0) { // 子进程执行命令 execvp(tokens[0], tokens); // 如果execvp返回,说明执行失败 perror("Command execution failed"); exit(EXIT_FAILURE); } else { // 父进程处理等待逻辑 if (!is_background) { waitpid(pid, NULL, 0); } else { printf("Background process started with PID: %d\n", pid); } } } return 0; }
内容的提问来源于stack exchange,提问作者Cmcbride
相关产品推荐
相关产品推荐

