【问题标题】:posix pipe as message queue: What happens on blocked write + signalposix管道作为消息队列:阻塞写入+信号会发生什么
【发布时间】:2016-07-10 11:09:02
【问题描述】:

我想使用管道作为内部消息队列,如下所述:posix pipe as a work queue

根据 glibc 的文档,如果数据小于 PIPE_BUF,则对管道的写入是原子的。 https://www.gnu.org/software/libc/manual/html_node/Pipe-Atomicity.html#Pipe-Atomicity

但是:如果出现信号,写入可能会被中断。让我们假设,write 被阻塞,因为管道快满了。现在出现了一个信号。这些数据会被原子地写入管道吗?

template <typename T>
ssize_t put(const T& data)
{       
    static_assert(sizeof(T) < PIPE_BUF, "We use the atomic property of the pipe write. So sizeof(T) MUST be smaller than PIPE_BUF");

    int written;
    const size_t id = T::value;
    written = write(m_fds[write_fd], &id, sizeof(size_t));
    assert(written == sizeof(size_t));

    const size_t sT = sizeof(T);
    write(m_fds[write_fd], &sT, sizeof(size_t));
    assert(written == sizeof(size_t));

    write(m_fds[write_fd], &data, sizeof(T)); // * this blocks in example
    assert(written == sizeof(T));

    return sizeof(T);
}

【问题讨论】:

    标签: c++ linux pipe message-queue atomic


    【解决方案1】:

    原子只是意味着 "the whole amount written in one operation is not interleaved with data from any other process."

    信号中断略有不同。根据the man page of signal,管道是一种“慢速设备”。因此,除非设置了SA_RESTART,否则write 操作将以写入的数据数量返回成功。因此,最好经常检查 write 的返回值,以确保所有数据都已写入。或者,您可以屏蔽可能的信号。

    【讨论】:

    • 谢谢!请问在这种情况下 writev() 的行为是否与 write 相同以将所有三个项目写入管道?否则我将需要一个互斥锁,而原子属性对我来说毫无用处。
    • 回答我的第二个问题:是的,它有效。 man7.org/linux/man-pages/man2/writev.2.html "readv() 和 writev() 执行的数据传输是原子的"
    猜你喜欢
    • 2012-04-12
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    相关资源
    最近更新 更多