在C中读/写结构到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 是指向我的结构的指针,它已分配,因此 fifo 或类似名称不存在问题。 如果我在没有 O_NONBLOCK 选项的情况下打开 fifo,它会第一次写入,但随后它会阻塞,因为我在读取结构时也遇到了麻烦。第一次之后,创建了初始 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 始终 <= 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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ENXIO
错误消息是“没有这样的设备或地址”。如果您查看open< /code>
手册页,您会看到报告此错误,特别是在以下情况下:
这正是你的情况。因此,您看到的行为是正常的:您无法写入(不阻塞)到没有读取器的管道。如果没有任何内容连接到管道进行读取,内核将不会缓冲您的消息。
因此,请确保在“生产者”之前启动“消费者”,或者删除生产者上的非阻塞选项。
顺便说一句:在大多数情况下,使用
access
是向 检查时间到使用时间问题。不要使用它。尝试一下mkfifo
- 如果它有效,那么你就很好了。如果失败并显示EEXISTS
,那么您也可以。如果否则失败,请清理并退出。对于问题的第二部分,这实际上完全取决于您尝试发送的数据的结构。在 C 中序列化随机结构根本不容易,特别是如果它包含变量数据(例如
char *
)。如果您的结构仅包含原始类型(并且没有指针),并且两侧都在同一台机器上(并使用相同的编译器编译),则一侧是原始
write
,而read< /code> 整个结构的另一个应该可以工作。
例如,您可以查看C - 序列化技术以获取更复杂的数据类型。
关于您的具体示例:您会混淆指向结构的指针和普通结构。
在写入方面,您有:
这是不正确的,因为
routing_table
是一个指针。您需要:读取端同样的东西。据我所知,在接收大小上,您也没有分配 updateData 。您也需要这样做(使用
malloc
,并记住释放它)。"No such device or address" is the
ENXIO
error message. If you look at theopen
man page, you'll see that this error is reported in particular if:which is exactly your situation. So the behavior you are seeing is normal: you can't write (without blocking) to a pipe that has no readers. The kernel won't buffer your messages if nothing is connected to the pipe for reading.
So make sure you start the "consumer(s)" before your "producer", or remove the non-blocking option on the producer.
BTW: using
access
is, in most circumstances, opening yourself to time of check to time of use issues. Don't use it. Try themkfifo
- if it works, you're good. If it fails withEEXISTS
, you're good too. If it fails otherwise, clean up and bail out.For the second part of your question, it really depends completely on how exactly the data you are trying to send is structured. Serializing a random struct in C is not easy at all, especially if it contains variable data (like
char *
s for example).If you struct contains only primitive types (and no pointers), and both sides are on the same machine (and compiled with the same compiler), then a raw
write
on one side andread
on the other of the whole struct should work.You can look at C - Serialization techniques for more complex data types for example.
Concerning your specific example: you're getting mixed up between pointers to your structs and plain structs.
On the write side you have:
This is incorrect since
routing_table
is a pointer. You need:Same thing on the read side. On the receiving size you're also not allocating
updateData
as far as I can tell. You need to do that too (withmalloc
, and remember to free it).