我正在用两个线程在Linux上编写一个进程。 它们使用通过pipe()
调用创build的匿名pipe道进行通信。
一端是将C结构复制到pipe道中:
struct EventStruct e; [...] ssize_t n = write(pipefd[1], &e, sizeof(e));
另一端从pipe道读取:
struct EventStruct e; ssize_t n = read(pipefd[0], &e, sizeof(e)); if(n != -1 && n != 0 && n < sizeof(e)) { // Is a partial read possible here?? }
可以使用匿名pipe道进行部分读取吗?
手册页( man 7 pipe
)规定,在PIPE_BUF大小下的任何写入都是primefaces的。 但他们的意思是primefaces关于其他作家线程…我不关心多个作家问题。 我只有一个作者线程,只有一个读者线程。
作为一个侧面说明,我的结构是56个字节长。 远低于Linux上至less4096字节的PIPE_BUF大小。 在最新的内核上它看起来更高。
另有说法:在阅读结束时,我是否必须处理部分阅读和存储它们,同时我收到一个完整的结构实例?
只要你处理固定大小的单位,就没有问题。 如果在管道上写入N个字节的单位,并且读取器从管道中请求N个字节的单位,则不存在问题。 如果你不能一下子阅读所有的数据(例如,在你阅读了它的长度之后,你就不知道大小),那么生活就会变得棘手。 但是,如图所示,你应该没问题。
也就是说,你应该仍然可以检测短的读取。 如果你读了一段短文,但是假设它是全长的话,那么这个灾难就是悬而未决的。 但是,你不应该期望检测短的读取 – 代码覆盖将是一个问题。 我只是测试n < (ssize_t)sizeof(e)
而检测到的任何东西都是错误或EOF。 注意演员; 否则,有符号值将被转换为无符号值, -1
不会被正确识别。
对于规范,你需要阅读POSIX规范:
read()
write()
pipe()
并可能跟踪来自这些页面的链接。 例如,对于write()
,规范说:
向管道或FIFO写入请求应按照与常规文件相同的方式进行处理,但以下情况除外:
不存在与管道相关的文件偏移量,因此每个写入请求都应附加到管道末端。
写入{PIPE_BUF}个字节或更少的请求不应与来自其他进程写入同一管道的数据交错。 大于{PIPE_BUF}字节的写入可能会在任意边界上与其他进程的写入交错,无论文件状态标志的O_NONBLOCK标志是否被设置。
或者从read()
的规范:
成功完成后,如果
nbyte
大于0,则read()
将标记为更新文件的最后一个数据访问时间戳,并返回读取的字节数。 这个数字不会大于nbyte
。 如果文件中剩余的字节数少于nbyte
,如果read()请求被信号中断,或者如果文件是管道或FIFO或特殊文件,并且少于nbyte
,返回的值可能小于nbyte
nbyte
字节立即可供阅读。 例如,来自与终端相关联的文件的read()
可以返回一个类型的数据行。
所以, write()
会写出原子单位; read()
只会读取原子单位,因为这是写的。 这不会有什么问题,这是我一开始就说的。