C语言模拟shell管道命令时出现Bad file descriptor错误求解
问题原因与修复方案
核心报错原因
你触发grep: (standard input): Bad file descriptor的直接问题出在first_cmd_exec函数的文件打开逻辑:
- 你打开第一个命令的输入文件时用了
O_WRONLY(只写)权限,随后又把这个只写的文件描述符通过dup2绑定到了STDIN_FILENO(标准输入),grep运行时需要从标准输入读取内容,尝试读取只写属性的文件描述符就会触发坏文件描述符错误。
其他需要修正的问题
- 输出文件打开参数不全:你打开第二个命令的输出文件仅用了
O_WRONLY参数,如果目标输出文件不存在会直接打开失败,建议补充O_CREAT | O_TRUNC标志,同时指定文件权限为0644,避免权限异常。 - 冗余代码:
last_cmd_exec末尾的exit(EXIT_SUCCESS)是无效代码,execve调用成功后会直接替换进程镜像,不会执行到后续代码,仅在execve调用失败时才会走到后面,你已经配置了execve失败的错误处理逻辑,这行可以直接删除。 - 资源泄漏:你在
dup2完成后没有关闭原本打开的输入/输出文件的原始描述符,虽然进程退出后系统会自动回收,但主动关闭可以避免描述符泄漏问题。
修复后的核心代码示例
void first_cmd_exec(t_command *cmd, char **envp, int *pipe_fd) { // 输入文件改为只读权限打开 if ((cmd->fd = open(cmd->file, O_RDONLY)) == -1) perror_exit("open"); if (close(pipe_fd[0]) == -1) perror_exit("close 1 1st cmd"); if (dup2(cmd->fd, STDIN_FILENO) == -1) perror_exit("dup2 1st cmd"); if (dup2(pipe_fd[1], STDOUT_FILENO) == -1) perror_exit("dup2 1st cmd"); // 关闭原文件描述符避免泄漏 close(cmd->fd); if (close(pipe_fd[1]) == -1) perror_exit("close 2 1st cmd"); if (execve(cmd->path_exec, cmd->tab_cmd, envp) == -1) perror_exit("execve 1st cmd"); }
void last_cmd_exec(t_command *cmd, char **envp, int *pipe_fd) { cmd = cmd->next; // 输出文件补充创建、清空标志,指定读写权限 if ((cmd->fd = open(cmd->file, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) perror_exit("open 2nd cmd"); if (close(pipe_fd[1]) == -1) perror_exit("close 1 2nd cmd"); if (dup2(cmd->fd, STDOUT_FILENO) == -1) perror_exit("dup2 2nd cmd"); if (dup2(pipe_fd[0], STDIN_FILENO) == -1) perror_exit("dup2 2nd cmd"); // 关闭原文件描述符避免泄漏 close(cmd->fd); if (close(pipe_fd[0]) == -1) perror_exit("close 2 2nd cmd"); if (execve(cmd->path_exec, cmd->tab_cmd, envp) == -1) perror_exit("execve 2nd cmd"); }
内容的提问来源于stack exchange,提问作者FoReal
相关产品推荐
相关产品推荐

