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

命名管道读写问题:多进程场景下的输出异常求助

Troubleshooting Named Pipe Issues Between 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

  1. First, test with one customer and one bank using the same pipe—confirm you get output before moving to two customers.
  2. Once single-pipe works, add the second pipe and implement select() or threads in the bank.
  3. Always check return values for open(), read(), write(), and select()—they'll tell you exactly where things are breaking.

内容的提问来源于stack exchange,提问作者JOhAnn4187

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:57:35