使用fdopen时出现Bad file descriptor错误的技术求助
Fixing "Bad file descriptor" Error with
fdopen in Pipe/Fork Setup Hey there! Let's figure out why you're hitting that "Bad file descriptor" error when using fdopen in your parent-child pipe setup. Your code is on the right track, but there are a few critical steps missing or misordered that are causing the issue. Let's break this down and fix it.
Common Causes of the Error
First, let's list the most likely culprits for this specific error in your pipe/fork scenario:
- Closing the wrong pipe file descriptor in the child process (e.g., closing the read end instead of the write end)
- Forgetting to close unused pipe ends in either parent or child (leads to invalid descriptor states)
- Using the wrong mode with
fdopen(e.g., trying to write to a pipe's read end) - Botching the STDIN redirection steps before executing
test3
Corrected Full Code
Here's a complete, working version of your code with explanations for each key step:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/wait.h> int main(int argc, char *argv[]) { int fd[2]; char buf[] = "HELLO WORLD!"; // Create pipe - check for failure explicitly if (pipe(fd) == -1) { perror("pipe"); return EXIT_FAILURE; } switch (fork()) { case -1: perror("fork"); // Clean up open pipe fds on error to avoid leaks close(fd[0]); close(fd[1]); return EXIT_FAILURE; case 0: // Child process // Child doesn't need the pipe's write end - close it immediately close(fd[1]); // Option 1: Redirect STDIN to pipe read end, then exec test3 // This is what you need to pass data to test3's STDIN if (dup2(fd[0], STDIN_FILENO) == -1) { perror("dup2"); close(fd[0]); exit(EXIT_FAILURE); } // Now STDIN points to the pipe, close the original read fd close(fd[0]); // Execute test3 - this replaces the child process with test3 execl("./test3", "test3", NULL); // If we reach here, execl failed perror("execl test3"); exit(EXIT_FAILURE); // Option 2: If you wanted to read in the child directly with fdopen // (not needed if you're exec-ing test3) // FILE *pipe_in = fdopen(fd[0], "r"); // if (!pipe_in) { // perror("fdopen"); // close(fd[0]); // exit(EXIT_FAILURE); // } // // Read from the pipe // char read_buf[100]; // fgets(read_buf, sizeof(read_buf), pipe_in); // printf("Child read: %s\n", read_buf); // fclose(pipe_in); // exit(EXIT_SUCCESS); default: // Parent process // Parent doesn't need the pipe's read end - close it close(fd[0]); // Write data to the pipe ssize_t bytes_written = write(fd[1], buf, strlen(buf)); if (bytes_written == -1) { perror("write"); } else { printf("Parent wrote %zd bytes: %s\n", bytes_written, buf); } // Close write end to signal EOF to child close(fd[1]); // Wait for child to finish to avoid zombie processes wait(NULL); return EXIT_SUCCESS; } }
Key Fixes Explained
Proper Pipe End Management:
- In the child, we close
fd[1](the write end) immediately because we only need to read from the pipe. If you accidentally closedfd[0]instead,fdopenwould try to open a closed descriptor, causing the "Bad file descriptor" error. - In the parent, we close
fd[0](the read end) since we only need to write to the pipe. Leaving unused ends open can prevent EOF signals and cause unexpected blocking.
- In the child, we close
STDIN Redirection for
test3:- To get
test3to read from the pipe, we usedup2(fd[0], STDIN_FILENO)to replace the child's standard input with the pipe's read end. After this, we close the originalfd[0]because it's no longer needed. - If you skip this step and try to use
fdopenbefore exec-ing,test3won't inherit that file pointer—exec replaces the entire process image, so you need to set up the file descriptors before callingexecl.
- To get
Error Handling & Cleanup:
- We add explicit cleanup of pipe descriptors on fork/pipe failure to avoid file descriptor leaks.
- We check the return value of
dup2andexeclto catch errors early.
fdopenUsage (If Needed):- If you weren't exec-ing
test3and wanted to read in the child directly, usefdopen(fd[0], "r")—make sure you're opening the read end with read mode. Using "w" here would cause the same "Bad file descriptor" error.
- If you weren't exec-ing
Final Checks
- Ensure
test3is compiled and exists in the same directory (or use the full path inexecl). - Verify that
test3reads from standard input (e.g., usesscanf,fgets, etc.).
内容的提问来源于stack exchange,提问作者Wolfat
相关产品推荐
相关产品推荐

