You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 02:36:31