yve*_*mes 3 c c++ linux multithreading posix
我正在Linux上用两个线程编写一个进程.它们使用通过pipe()调用创建的匿名管道进行通信.
一端是将C结构复制到管道中:
struct EventStruct e;
[...]
ssize_t n = write(pipefd[1], &e, sizeof(e));
Run Code Online (Sandbox Code Playgroud)
另一端从管道中读取它:
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??
}
Run Code Online (Sandbox Code Playgroud)
可以使用匿名管道进行部分读取吗?
手册页(man 7 pipe)规定PIPE_BUF大小下的任何写入都是原子的.但他们的意思是关于其他作家线程的原子......我不关心多个作家问题.我只有一个编写器线程,只有一个读者线程.
作为旁注,我的结构长度为56个字节.远低于PIPE_BUF大小,在Linux上至少为4096字节.看起来它在最近的内核上甚至更高.
否则:在阅读结束时,我是否必须处理部分读取并存储它们同时我收到一个完整的结构实例?
只要您处理固定大小的单位,就没有问题.如果你在管道上写一个N字节的单位,并且阅读器从管道请求一个N字节的单位,那么就没有问题.如果你不能一下子读取所有数据(例如,在你读完它的长度后你就不知道它的大小),那么生活会变得更加棘手.但是,如图所示,你应该没问题.
也就是说,您仍应检测短读.如果你得到一个简短的阅读但是假设它是全长的,那么就有一个灾难待决.但是,您不应期望检测到短读取 - 代码覆盖率将是一个问题.我只是测试n < (ssize_t)sizeof(e)并检测到任何错误或EOF.注意演员表; 否则,签名值将转换为无符号值,并且-1不会被正确发现.
对于规范,您需要阅读POSIX规范:
并可能跟踪这些页面的链接.例如,因为write(),规范说:
对管道或FIFO的写入请求应以与常规文件相同的方式处理,但以下情况除外:
没有与管道关联的文件偏移量,因此每个写入请求都应附加到管道的末尾.
{PIPE_BUF}字节或更少字节的写请求不应与来自在同一管道上执行写操作的其他进程的数据交错.无论是否设置了文件状态标志的O_NONBLOCK标志,大于{PIPE_BUF}字节的写入都可以在任意边界上与其他进程进行写入交错.
或者从以下规范read():
成功完成后,如果
nbyte大于0,read()则应标记更新文件的最后一个数据访问时间戳,并返回读取的字节数.这个数字永远不会大于nbyte.返回的值可能小于nbyte文件中剩余的字节数小于nbyte,如果read()请求被信号中断,或者文件是管道或FIFO或特殊文件并且nbyte立即少于字节可供阅读.例如,read()来自与终端相关联的文件的a可以返回一个类型化的数据行.
所以,write()会写原子单位; 在read()将只读取的原子单位,因为这是写.这不会有问题,这就是我在开始时所说的.