3

我正在尝试使用命名管道在进程之间传递结构。我被困在试图打开管道非阻塞模式。这是我写入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,它会第一次写入 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总是<=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;
4

1 回答 1

3

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

O_NONBLOCK | O_WRONLY 已设置,命名文件是 FIFO,并且没有进程打开文件以供读取。(...)

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

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

顺便说一句:access在大多数情况下,使用是让自己接受检查时间和使用时间问题。不要使用它。试试mkfifo- 如果它有效,你很好。如果它失败了EEXISTS,你也很好。如果否则失败,请清理并退出。

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

如果您的 struct 仅包含原始类型(并且没有指针),并且双方都在同一台机器上(并使用相同的编译器编译),那么整个结构的write一侧和另一侧的 raw 应该可以工作。read

例如,您可以查看C -更复杂数据类型的序列化技术。

关于您的具体示例:您在指向结构的指针和普通结构之间混淆了。

在写入方面,您有:

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));
于 2011-05-21T09:14:00.020 回答