在C中读/写struct到fifo

时间:2011-05-21 08:45:55

标签: c struct fifo

我正在尝试使用命名管道在进程之间传递结构。我试图打开管道非阻塞模式时遇到困难。这是我写入fifo的代码:

void writeUpdate() {
    // Create fifo for writing updates:
    strcpy(fifo_write, routing_table->routerName);
    // Check if fifo exists:
    if(access(fifo_write, F_OK) == -1 )
        fd_write = mkfifo(fifo_write, 0777);
    else if(access(fifo_write, F_OK) == 0) {
        printf("writeUpdate: FIFO %s already exists\n", fifo_write);
        //fd_write = open(fifo_write, O_WRONLY|O_NONBLOCK);
    }
    fd_write = open(fifo_write, O_WRONLY|O_NONBLOCK);
    if(fd_write < 0)
        perror("Create fifo error");
    else {
        int num_bytes = write(fd_write, routing_table, sizeof(routing_table));
        if(num_bytes == 0)
            printf("Nothing was written to FIFO %s\n", fifo_write);
        printf("Wrote %d bytes. Sizeof struct: %d\n", num_bytes,sizeof(routing_table)+1);
        }
    close(fd_write);
   }

routing_table是指向我的struct的指针,它被分配了,所以没有像fifo或smth这样的名字的概率。  如果我在没有O_NONBLOCK选项的情况下打开fifo,它第一次写入smth,但随后它会阻塞,因为我也在阅读这个结构时遇到麻烦。并且在第一次之后,创建了初始fifo,但是出现了其他fifo,名为'。','..'。  设置O_NONBLOCK选项后,它会创建fifo,但总是会抛出错误:'没有这样的设备或地址'。知道为什么会这样吗?感谢。

编辑:好的,所以我现在很清楚打开fifo,但我有另一个问题,实际上读取/写入结构到fifo是我的问题。我的代码来读取结构:

void readUpdate() {
struct rttable *updateData;
allocate();

strcpy(fifo_read, routing_table->table[0].router);

// Check if fifo exists:
if(access(fifo_read, F_OK) == -1 )
    fd_read = mkfifo(fifo_read, 777);
else if(access(fifo_read, F_OK) == 0) {
    printf("ReadUpdate: FIFO %s already exists\n Reading from %s\n", fifo_read, fifo_read);        
}
fd_read = open(fifo_read, O_RDONLY|O_NONBLOCK);
int num_bytes = read(fd_read, updateData, sizeof(updateData));
close(fd_read);
if(num_bytes > 0) {
    if(updateData == NULL)
        printf("Read data is null: yes");
    else
        printf("Read from fifo: %s %d\n", updateData->routerName, num_bytes);

    int result = unlink(fifo_read);
    if(result < 0)
        perror("Unlink fifo error\n");
    else {
        printf("Unlinking successful for fifo %s\n", fifo_read);
        printf("Updating table..\n");
        //update(updateData);
        print_table_update(updateData);
    }
} else
    printf("Nothing was read from FIFO %s\n", fifo_read);
}

它打开fifo并尝试读取,但似乎没有任何内容在fifo中,尽管在writeUpdate中第一次它说它写了4个字节(这似乎也是错误的)。在阅读时,第一次打印'a'然后num_bytes总是&lt; = 0。    我环顾四周,发现这个例子,只需简单的写入/读取,编写结构时是否需要更多的东西?

我的结构看起来像这样:

typedef struct distance_table {
char dest[20];       //destination network
char router[20];     // via router..
int distance;
} distance_table;

typedef struct rttable {
char routerName[10];
char networkName[20];
struct distance_table table[50];
int nrRouters;
} rttable;

struct rttable *routing_table;

1 个答案:

答案 0 :(得分:3)

“没有此类设备或地址”是ENXIO错误消息。如果查看open手册页,您会看到特别是在以下情况下报告此错误:

  

O_NONBLOCK |设置了O_WRONLY,命名文件是FIFO而没有进程                 将文件打开以供阅读。 (...)

这正是你的情况。所以你看到的行为是正常的:你不能写(没有阻塞)到没有读者的管道。如果没有任何东西连接到管道进行读取,内核将不会缓冲您的消息。

因此,请确保在“生产者”之前启动“消费者”,或删除生产者的非阻止选项。

顺便说一句:在大多数情况下,使用access会让自己陷入time of check to time of use问题。不要使用它。试试mkfifo - 如果有效,那就很好。如果它以EEXISTS失败,那你也很好。如果否则失败,清理并纾困。

对于问题的第二部分,它实际上完全取决于您尝试发送的数据的结构。在C中序列化随机结构并不容易,特别是如果它包含可变数据(例如char *)。

如果struct只包含原始类型(并且没有指针),并且双方都在同一台机器上(并使用相同的编译器进行编译),那么一侧是原始writeread在整个结构的另一个应该工作。

例如,您可以查看C - Serialization techniques以了解更复杂的数据类型。

关于你的具体例子:你在结构和平面结构的指针之间混淆了。

在写作方面你有:

int num_bytes = write(fd_write, routing_table, sizeof(routing_table));

这是不正确的,因为routing_table是一个指针。你需要:

int num_bytes = write(fd_write, routing_table, sizeof(*routing_table));
// or sizeof(struct rttable)

阅读方面也是如此。就接收大小而言,就我所知,你也没有分配updateData。你也需要这样做(使用malloc,并记住释放它。)

struct rttable *updateData = malloc(sizeof(struct rrtable));