我正在尝试使用命名管道在进程之间传递结构。我试图打开管道非阻塞模式时遇到困难。这是我写入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;
答案 0 :(得分:3)
“没有此类设备或地址”是ENXIO
错误消息。如果查看open
手册页,您会看到特别是在以下情况下报告此错误:
O_NONBLOCK |设置了O_WRONLY,命名文件是FIFO而没有进程 将文件打开以供阅读。 (...)
这正是你的情况。所以你看到的行为是正常的:你不能写(没有阻塞)到没有读者的管道。如果没有任何东西连接到管道进行读取,内核将不会缓冲您的消息。
因此,请确保在“生产者”之前启动“消费者”,或删除生产者的非阻止选项。
顺便说一句:在大多数情况下,使用access
会让自己陷入time of check to time of use问题。不要使用它。试试mkfifo
- 如果有效,那就很好。如果它以EEXISTS
失败,那你也很好。如果否则失败,清理并纾困。
对于问题的第二部分,它实际上完全取决于您尝试发送的数据的结构。在C中序列化随机结构并不容易,特别是如果它包含可变数据(例如char *
)。
如果struct只包含原始类型(并且没有指针),并且双方都在同一台机器上(并使用相同的编译器进行编译),那么一侧是原始write
而read
在整个结构的另一个应该工作。
例如,您可以查看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));