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

C语言命名管道读取错误值问题排查求助

命名管道通信错误:读取结果始终为错误值

我编写了两个进程handler.c和calculate.c,二者通过命名管道实现通信。handler.c接收命令行传入的操作数与运算符,将其发送至calculate.c,随后读取计算结果并打印;calculate.c从管道读取操作数和运算符,执行计算后将结果写入管道。但目前遇到问题:无论进行何种操作,handler.c从管道读取结果时始终得到错误值822096384。

HANDLER.C 原代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
    char* name = argv[1];// pipe name
    int a, b;
    
    int fd = open(name, O_RDWR);
    
    a=atoi(argv[3]);
    b=atoi(argv[4]);

    write(fd, &a, sizeof(int));
    sleep(1);
    write(fd, &b, sizeof(int));
    sleep(1);
    write(fd, argv[2], sizeof(argv[2]));
    int res = 0;
    sleep(1);
    read(fd, &res, sizeof(int)); //it read the wrong value i.e. 822096384
    printf("%d", res);
    printf("\n %s %s %s = %d\n", argv[3], argv[2], argv[4], res);
    close(fd);

return 0;
}

CALCULATE.C 原代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
    char* name = argv[1];   
    int res = 0;
    int a,b;
    char o;
    int fd = open(name, O_RDWR);
    


    read(fd, &a, sizeof(int));
    printf("op1: %d ", a);
    sleep(1);
    read(fd, &b, sizeof(int));
    printf("op2: %d ", b);
    sleep(1);
    read(fd, &o, sizeof(char));
    printf("operator: %c ", o);

    if(strcmp(&o, "+") == 0)//if(o = '+')
    {
        res = a + b;
    }

    else if(strcmp(&o, "/") == 0)
    {
        res = a / b;
    }

    else if(strcmp(&o, "-") == 0)
    {
        res = a - b;    
    }

    else if(strcmp(&o, "*") == 0)
    {
        res = a * b;
    }
    printf("result: %d\n", res); //here res have the correct value
    write(fd, &res, sizeof(res));
    close(fd);
return 0;
}

运行输出

handler.c 运行输出

User@V-Ubuntu:~/Desktop/pipes$ ./handler pipe + 2 1
822096384
 2 + 1 = 822096384

calculate.c 运行输出

User@V-Ubuntu:~/Desktop/pipes$ ./calculate pipe
op1: 2 op2: 1 operator: + result: 3

问题原因及修复方案

1. 命名管道读写模式错误

两个进程都用O_RDWR打开管道,导致每个进程同时拥有读写端。handler.c最后读取时,会读到自己写操作残留的垃圾数据,而非calculate.c写入的结果。

修复:拆分读写操作,handler.c先以O_WRONLY打开管道发送数据,关闭后再以O_RDONLY打开读取结果;calculate.c先以O_RDONLY打开读取请求,关闭后再以O_WRONLY打开写入结果。

2. 运算符写入错误

原代码中write(fd, argv[2], sizeof(argv[2]))会写入指针大小的字节(64位系统为8字节),但我们只需要单个运算符字符。且argv[2]是字符串,应取第一个字符argv[2][0]。

修复:改为write(fd, &argv[2][0], sizeof(char))。

3. 运算符比较错误

strcmp(&o, "+")用于比较字符串,但&o是单个字符的地址,并非以\0结尾的字符串,会导致越界访问。

修复:直接用字符比较if (o == '+')替代strcmp。

4. 依赖sleep同步不可靠

用sleep(1)保证同步的方式不可靠,应利用管道的阻塞特性自然同步,删除所有sleep调用。


修复后的代码

修复后的 HANDLER.C

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
    char* name = argv[1];
    int a, b;
    
    // 打开管道发送请求
    int fd_write = open(name, O_WRONLY);
    if (fd_write == -1) {
        perror("open write pipe failed");
        exit(1);
    }
    
    a = atoi(argv[3]);
    b = atoi(argv[4]);

    write(fd_write, &a, sizeof(int));
    write(fd_write, &b, sizeof(int));
    write(fd_write, &argv[2][0], sizeof(char));
    
    close(fd_write);

    // 打开管道读取结果
    int fd_read = open(name, O_RDONLY);
    if (fd_read == -1) {
        perror("open read pipe failed");
        exit(1);
    }
    
    int res = 0;
    read(fd_read, &res, sizeof(int));
    printf("%d\n", res);
    printf("%s %s %s = %d\n", argv[3], argv[2], argv[4], res);
    
    close(fd_read);

    return 0;
}

修复后的 CALCULATE.C

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
    char* name = argv[1];   
    int res = 0;
    int a, b;
    char o;
    
    // 打开管道读取请求
    int fd_read = open(name, O_RDONLY);
    if (fd_read == -1) {
        perror("open read pipe failed");
        exit(1);
    }

    read(fd_read, &a, sizeof(int));
    printf("op1: %d ", a);
    read(fd_read, &b, sizeof(int));
    printf("op2: %d ", b);
    read(fd_read, &o, sizeof(char));
    printf("operator: %c ", o);

    if (o == '+') {
        res = a + b;
    } else if (o == '/') {
        res = a / b;
    } else if (o == '-') {
        res = a - b;    
    } else if (o == '*') {
        res = a * b;
    }
    
    printf("result: %d\n", res);
    close(fd_read);

    // 打开管道写入结果
    int fd_write = open(name, O_WRONLY);
    if (fd_write == -1) {
        perror("open write pipe failed");
        exit(1);
    }
    write(fd_write, &res, sizeof(res));
    close(fd_write);

    return 0;
}

运行说明

  1. 先创建命名管道:mkfifo pipe
  2. 启动计算进程:./calculate pipe
  3. 启动处理进程并传入参数:./handler pipe + 2 1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:47:12