【问题标题】:Passing a struct trough a pipe in C通过C中的管道传递结构
【发布时间】:2020-01-21 12:41:23
【问题描述】:

考虑以下结构:

struct msg { 
   int id;
   int size;
   double *data;
}

现在,该结构将用于通过管道在生产者和消费者进程之间进行通信。

事实上,由于data 指针,它不起作用...所以必须将其更改为实际数据(而不是指向数据的指针)。但复杂的原因在于生产者必须能够发送任意数量的数据(接收者......相应地工作)。

有人可以吗,请指点我一个解决方案? 具体来说:

  • 定义数据结构的最佳解决方案是什么?
  • char* c_data 联合(将其传递给写入)是否可行?
  • 如何实现read进行大小核算?

非常感谢您的反馈。

【问题讨论】:

  • 您不能在现代受保护系统上的进程之间传输指针。指针对单个进程是私有的,不能被不同的进程使用(即使它是从同一个可执行程序启动的)。
  • 编写一个序列化和反序列化函数,将结构转换为抽象的东西,你可以在另一端阅读。您甚至可以将数据转换为字符串 "123 456 789.123" 并将其发送并使用 printf/scanf 函数。
  • @Someprogrammerdude:问题承认并声明 OP 试图发送 double 数据(可能是该位置的数组),而不是 double * 值。
  • 您可以简单地将id的内容、size的内容、size_t(或其他适合您的整数)的内容写入管道,其中包含@的数量987654333@ 值被发送(假设这不是 size 已经是),然后是 double 值。只要您使用相同的对象表示写入进程,您就可以发送double 对象的原始字节;无需专门对它们进行序列化。在接收器中,读取idsize 的值和double 项的数量,然后读取指定数量的double 值。
  • 数组中已经有一个size 元素。看来您想使用旧式 VLA 并执行 struct msg{ int id; size_t size; double data[0]; }

标签: c pipe


【解决方案1】:

不幸的是,没有通过管道发送任意对象的本地方式。但是,您可以通过 fread() and fwrite() 发送原始数据来轻松实现您想要的,这是一种以二进制形式序列化数据的非常简单的方法。

请记住,为了使以下内容正常工作,生产者和消费者程序需要在同一台机器上编译,使用相同的数据结构定义和可能相同的编译器标志。

这是一个简单的解决方案:

  1. 创建一个供生产者和接收者使用的标头结构的通用定义:

    struct msg_header { 
        int id;
        int size;
    };
    

    这将保存有关真实data 的信息。我建议你使用size_t 来存储大小,因为它是无符号的,更适合这个目的。

  2. producer中,准备要发送的数据以及正确的header,例如:

    struct msg_header header = {.id = 0, .size = 4};
    double *data = {1.23, 2.34, 3.45, 4.56};
    

    显然不需要这样声明,甚至可以通过malloc()动态调整大小和分配,重要的是你知道大小。

  3. 还是在生产者中,通过管道发送header后面跟着数据:

    // Use fdopen() if you don't already have a FILE*, otherwise skip this line.
    FILE *pipe = fdopen(pipe_fd, "w");
    
    // Send the header through the pipe.
    fwrite(&header, sizeof(header), 1, pipe);
    
    // Send the data through the pipe.
    fwrite(&data, sizeof(*data), header.size, pipe);
    
  4. consumer中,读取header,然后使用.size值读取正确的数据量:

    // Use fdopen() if you don't already have a FILE*, otherwise skip this line.
    FILE *pipe = fdopen(pipe_fd, "r");
    
    struct msg_header header;
    double *data;
    
    // Read the header from the pipe.
    fread(&header, sizeof(header), 1, pipe);
    
    // Allocate the memory needed to hold the data.
    data = malloc(sizeof(*data) * header.size);
    
    // Read the data from the pipe.
    fread(&data, sizeof(*data), header.size, pipe);
    

请记住,您必须在上述每个函数调用之后检查错误。我没有在我的示例中添加错误检查只是为了使代码更简单。有关详细信息,请参阅手册页。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多