命名管道读写问题:多进程场景下的输出异常求助
customer.c and bank.c Hey there! Let's walk through what's likely causing your FIFO (named pipe) headaches—this stuff has tripped up plenty of folks, so we'll get it sorted out.
Common Root Causes & Fixes
1. Blocking Open Behavior Is Stalling Your Single-Customer Test
Named pipes have a key quirk: by default, a process calling open() on a FIFO will block until the opposite end is opened too. So if you run one customer.c pointing to atm2 but your bank.c is only listening on atm1, both processes will hang indefinitely waiting for the other side to connect—hence no output.
Quick Fix for Testing:
- Hardcode both programs to use the same pipe first (e.g.,
atm1) to rule out mismatched pipe names. - Always check the return value of
open()to catch errors:// In bank.c (read side) int fd = open("atm1", O_RDONLY); if (fd == -1) { perror("Failed to open atm1 for reading"); exit(EXIT_FAILURE); } // In customer.c (write side) int fd = open("atm1", O_WRONLY); if (fd == -1) { perror("Failed to open atm1 for writing"); exit(EXIT_FAILURE); }
2. Incomplete/Incorrect Integer Reads/Writes
Since you're sending int data, you need to guarantee that exactly sizeof(int) bytes are read and written. Partial reads/writes (or ignoring return values from read()/write()) will cause missing or corrupted data, especially when running multiple customers.
Fix the Data Transfer Logic:
// In bank.c (proper read) int received_val; ssize_t bytes_read = read(fd, &received_val, sizeof(int)); if (bytes_read == sizeof(int)) { printf("Received value: %d\n", received_val); } else if (bytes_read == -1) { perror("Error reading from pipe"); } else { fprintf(stderr, "Warning: Got %zd bytes instead of %zu for int\n", bytes_read, sizeof(int)); } // In customer.c (proper write) int send_val = 42; // Example value ssize_t bytes_written = write(fd, &send_val, sizeof(int)); if (bytes_written != sizeof(int)) { perror("Error writing to pipe (partial write)"); }
3. Concurrent Pipe Handling Fails With Multiple Customers
When running two customer.c instances (one for each pipe), your bank.c can't just block on reading a single pipe—it'll ignore the other pipe entirely. You need a way to listen for data on both pipes at once.
Two Solid Solutions:
Option A: Use select() to Monitor Multiple Pipes
This lets your bank process wait for data on either atm1 or atm2 without blocking on one:
#include <sys/select.h> int main() { // Open both pipes in non-blocking mode to avoid initial hangs int fd_atm1 = open("atm1", O_RDONLY | O_NONBLOCK); int fd_atm2 = open("atm2", O_RDONLY | O_NONBLOCK); if (fd_atm1 == -1 || fd_atm2 == -1) { perror("Failed to open pipes"); exit(EXIT_FAILURE); } int max_fd = (fd_atm1 > fd_atm2) ? fd_atm1 : fd_atm2; fd_set read_fds; while (1) { FD_ZERO(&read_fds); FD_SET(fd_atm1, &read_fds); FD_SET(fd_atm2, &read_fds); // Wait for activity on either pipe int ret = select(max_fd + 1, &read_fds, NULL, NULL, NULL); if (ret == -1) { perror("select() failed"); break; } // Check atm1 for data if (FD_ISSET(fd_atm1, &read_fds)) { int val; ssize_t r = read(fd_atm1, &val, sizeof(int)); if (r == sizeof(int)) { printf("From atm1: %d\n", val); } } // Check atm2 for data if (FD_ISSET(fd_atm2, &read_fds)) { int val; ssize_t r = read(fd_atm2, &val, sizeof(int)); if (r == sizeof(int)) { printf("From atm2: %d\n", val); } } } close(fd_atm1); close(fd_atm2); unlink("atm1"); unlink("atm2"); return 0; }
Option B: Use Separate Threads for Each Pipe
If you prefer thread-based code, spawn one thread to block-read atm1 and another for atm2—each thread handles its own pipe independently.
4. Leftover Pipe Files Cause Weird Behavior
If your processes crash unexpectedly, the FIFO files (atm1/atm2) stick around on the filesystem. Reusing these can lead to unexpected blocking or errors.
Fix:
- Add cleanup logic to your bank program to delete the pipes on exit:
void cleanup() { unlink("atm1"); unlink("atm2"); } int main() { atexit(cleanup); // Rest of your code... } - Or manually delete them before each run with:
rm -f atm1 atm2
Testing Step-by-Step
- First, test with one customer and one bank using the same pipe—confirm you get output before moving to two customers.
- Once single-pipe works, add the second pipe and implement
select()or threads in the bank. - Always check return values for
open(),read(),write(), andselect()—they'll tell you exactly where things are breaking.
内容的提问来源于stack exchange,提问作者JOhAnn4187

