基于C语言使用Fork执行文本文件中命令的程序问题排查
读取文件命令并通过fork执行的C程序问题排查
我想要编写一个C程序,读取文本文件中的命令并将其存入数组,再通过fork函数逐个执行这些命令,以下是我的部分代码和数据文件,需要帮助排查问题:
原代码
void Execfile(char*filename) { char**T; int nb; FILE*f; char buff[MAX_ARG]; f=fopen("data1.txt","rb"); while(fgets(buff,MAX_ARG,f)!=NULL){ T=File2TabArgv(filename,&nb); } fclose(f); execvp(T[0],T); printf("\n"); printf("END"); }
数据文件(data1.txt)内容
sleep20
代码中的核心问题
- 文件名硬编码:函数参数
filename未被使用,硬编码成固定的data1.txt,无法灵活指定输入文件。 - 命令解析逻辑错误:循环中每次调用
File2TabArgv时传入的是文件名而非当前读取的行内容buff,相当于反复解析整个文件而非单条命令。 - 未使用fork创建子进程:直接调用
execvp会替换当前进程,后续的printf("END")永远不会执行,也无法实现“逐个执行多个命令”的需求。 - 文件打开模式错误:用
rb二进制模式读取文本文件,可能导致行尾处理异常,应使用r文本模式。 - 缺乏错误处理:未检查
fopen是否成功,若文件不存在会直接崩溃。 - 命令格式错误:数据文件中的
sleep20是无效命令,系统中不存在名为sleep20的程序,正确格式应为sleep 20。 - 内存泄漏风险:
T每次循环被重新赋值,之前分配的内存未释放,会造成内存泄漏。
修正后的示例代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #define MAX_ARG 256 // 简单实现命令字符串到argv数组的解析函数 char** File2TabArgv(char* cmd, int* arg_count) { char** argv = NULL; int count = 0; // 按空格和换行分割字符串 char* token = strtok(cmd, " \n"); while (token != NULL) { argv = realloc(argv, (count + 2) * sizeof(char*)); argv[count++] = strdup(token); token = strtok(NULL, " \n"); } if (argv != NULL) { argv[count] = NULL; // argv必须以NULL结尾 } *arg_count = count; return argv; } void Execfile(char* filename) { // 以文本模式打开文件,检查是否成功 FILE* f = fopen(filename, "r"); if (f == NULL) { perror("打开文件失败"); return; } char buff[MAX_ARG]; while (fgets(buff, MAX_ARG, f) != NULL) { // 跳过空行 if (strlen(buff) <= 1) continue; // 创建子进程执行命令 pid_t pid = fork(); if (pid == -1) { perror("创建子进程失败"); continue; } else if (pid == 0) { // 子进程中解析命令并执行 int arg_count; char** cmd_argv = File2TabArgv(buff, &arg_count); if (cmd_argv != NULL && cmd_argv[0] != NULL) { execvp(cmd_argv[0], cmd_argv); // 若execvp返回,说明执行失败 perror("命令执行失败"); // 释放解析时分配的内存 for (int i = 0; i < arg_count; i++) { free(cmd_argv[i]); } free(cmd_argv); exit(EXIT_FAILURE); } exit(EXIT_FAILURE); } else { // 父进程等待子进程执行完成,确保命令逐个执行 waitpid(pid, NULL, 0); } } fclose(f); printf("END\n"); } int main(int argc, char* argv[]) { if (argc != 2) { fprintf(stderr, "用法: %s <文件名>\n", argv[0]); return 1; } Execfile(argv[1]); return 0; }
关键修改说明
- 改用函数传入的
filename参数打开文件,支持灵活指定输入文件。 - 每次循环处理当前读取的行内容
buff,解析为命令参数数组。 - 通过
fork创建子进程执行命令,父进程等待子进程完成后再处理下一条命令。 - 添加了文件打开、进程创建、命令执行的错误处理,避免程序崩溃。
- 修正了数据文件中的命令格式,需改为
sleep 20才能正常执行。 - 补充了内存释放逻辑,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Neerus
相关产品推荐
相关产品推荐

