unistd.h read() 正在读取更多数据然后被写入

Posted

技术标签:

【中文标题】unistd.h read() 正在读取更多数据然后被写入【英文标题】:unistd.h read() is reading more data then being written 【发布时间】:2009-05-16 20:21:13 【问题描述】:

我正在从命名管道读取/写入数据。在写入方面,它说它正在写入一个恒定的 110 字节。在阅读方面,大部分时间它说它正在读取 110 个字节,这是正确的,但其他时候它说它正在读取 220 个字节或 330 个字节。事实上,当我打印它时,它会在同一个 read() 中连续打印两到三遍相同的消息。在下面的阅读代码中,我是否对 memset 做错了什么来清除字符?我想不出任何其他方式,它读取的内容比写入的内容多,除非缓冲区中剩下一些东西。

int fd1, numread;
char bufpipe[5000];

    while(1)
    
        fd1 = open("/tmp/testPipe", O_RDONLY);
        numread = read(fd1,bufpipe, 5000);//->this should always be 110
        if(numread > 1)
        
            printf("READ: %i", numread); 
            bufpipe[numread+1] = '\0';
            memset(bufpipe,'\0',5001);
            close(fd1);
        
    

【问题讨论】:

【参考方案1】:

这个:

memset(bufpipe,'\0',5001);

正在覆盖一个字节,因为您只有 5000 个字节。

但主要的“问题”是read(..., 5000) 将始终读取最多 5000 个字节的内容 - 您似乎假设它只会读取作者一次性写入的内容,这不是真的。如果写入器在两次读取之间写入两个 110 字节的数据包,那么读取器读取 220 字节是完全正确的。

如果您一次只需要读取一个数据包,则必须使数据包具有自描述性。例如,前四个字节包含后面的字节数。然后,您可以通过读取四个字节来读取单个数据包,将其转换为整数,然后读取该数量的数据字节。

【讨论】:

你先生是我的英雄。万万没想到,谢谢【参考方案2】:

您认为read 将在write 之后立即执行的假设不成立。在遇到读取之前,写入器进程可能会多次写入管道。写入的数据将被添加到缓冲区的末尾。换句话说,读写不是面向数据包的。它们是面向流的。这意味着write 只是将数据添加到缓冲区,read 只是获取可用的任何内容。

【讨论】:

【参考方案3】:

你是如何与作者同步的? 您只需阅读您的期望(指定 110 为 read())

【讨论】:

有没有办法在不知道会发生什么的情况下做到这一点?在这种情况下读取的数量可以是任意数量。这就是为什么我把它设置在 5000 这么高,即使它只写 110 您需要您的数据包在开始时包含它们的长度,因此您可以先读取长度,然后再读取正确的字节数以获取该单个数据包的其余部分。请参阅我修改后的答案。

以上是关于unistd.h read() 正在读取更多数据然后被写入的主要内容,如果未能解决你的问题,请参考以下文章

Read(),Write()

C语言用read封装/实现一个readline函数,读取文件一行 or 最后一行

read/write函数与(非)阻塞I/O的概念

C语言用read封装/实现一个readline函数,读取文件一行 or 最后一行

read的Linux C函数

Android C++系列:Linux文件IO操作