执行此操作是否安全:

int fd;

void thread_main()
{
    char buf[M];
    ssize_t r = read(fd, buf, M);
    assert(r == M);
    ...
}

int main()
{
    fd = open("/dev/urandom", O_RDONLY);

    for (int i = 0; i < N; i++)
         start_thread(i);

    for (int i = 0; i < N; i++)
         join_thread(i);
}

也就是说:在从主线程中将open(2)编码为"/dev/urandom"之后,从不同线程上下文中不同步它的read(2)是否安全?

断言在什么情况下会被开火?两个线程会获得相同的数据吗?可能出什么问题了?

最佳答案

您的代码是安全的,因为它不会崩溃。 assert将永远不会触发。没有两个线程会(应该)获得相同的随机数据(这是极不可能的,但两个线程也有可能获得两个偶然地相同的“不同”随机序列,因此不能100%保证)。
/dev/urandom绝不会阻塞或返回比您尝试读取的字节少的字节,但是,如果您读取的字节数足够多,它将最终耗尽熵,因此随机数的质量最终将略有下降。通常,这仍然足够好,并且还需要一段时间才能实现,但这是需要注意的事情(大多数人不需要关心,但这可能 Not Acceptable ,具体取决于您的操作) 。
read/write是线程安全的(因为它们不会崩溃或损坏数据或使描述符保持未定义状态),并且在这种特殊情况下,也不应在对不同进程的读取/写入之间混合/分割字节。但是,通常,read/write 不保证此。在某些设备上,它们可能会在并发读/写操作中混合数据。

但是,这应该不成问题,因为如果您获得一些其他随机位而其他人在两者之间获得了(不同的)位,则随机位仍然是随机的。
如果您认为这对您来说是个问题,请使用readv,它可以保证严格的原子性(永远不要混合/混合)。进出readv/writev的所有内容始终作为一个原子单位进行处理(如在管道上,当超过PIPE_BUF的大小时,如rodrigo所指出)。

关于c - Linux 3.5 : Safe to `read(2)` from same fd `open(2)` `/dev/urandom` from multiple threads?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12245054/

10-10 06:35