【问题标题】:Read/Write struct to fifo in C在C中读/写结构到fifo
【发布时间】:2011-08-30 03:41:37
【问题描述】:

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

我的结构如下所示:

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;

【问题讨论】:

    标签: c struct fifo


    【解决方案1】:

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

    O_NONBLOCK |设置了 O_WRONLY,命名文件为 FIFO 且无进程 已打开文件以供阅读。 (...)

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

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

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

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

    如果您的 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));
    

    【讨论】:

    • 你说得对,但我必须编写结构来说明 3-5 个其他进程,并且为每个进程打开一个不同的 fifo。如果“消费者”进程之一没有读取数据,我的整个生产者进程就会挂起。所以我想定期写入 fifo 并以某种方式检查消费者是否读取数据。整个目的是模拟路由协议(距离向量),不确定我是否有最好的想法。
    • 当您在open 上收到该错误时,您就知道没有消费者,因此没有必要写 - 另一端没有人在阅读。所以你的方法适用于O_NONBLOCK - 你知道消费者没有阅读。
    • 使用 access() 也是错误的另一个原因,因为它不一定检查您的有效权限。
    • 感谢您的回答,现在所有关于阻塞/非阻塞的问题都清楚了。我已经编辑了我的问题,因为这不是我发布的主要原因。
    • @joanna:这是一个完全不同的问题,如果不查看您正在使用的结构的定义,就无法真正回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 2023-03-04
    • 2014-01-11
    • 1970-01-01
    • 2019-06-06
    相关资源
    最近更新 更多