Linux 3.5:从多个线程安全地从同一个fd`open(2)``/ dev / urandom`中读取(2)`

时间:2012-09-03 09:18:27

标签: c linux multithreading pthreads linux-device-driver

这样做是否安全:

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)是不安全的?

在什么情况下断言会引发火灾?两个线程会得到相同的数据吗?可能出现什么问题?

2 个答案:

答案 0 :(得分:6)

您的代码是安全的,因为它不会崩溃。 assert永远不会触发。没有两个线程(应该)得到相同的随机数据(这是非常不可能的,但仍然有可能两个线程得到两个“不同”的随机序列 inlateide 相同,所以这不能100%保证。)

/dev/urandom永远不会阻止或返回比您尝试读取的字节数更少的字节数,但是,如果读取的数量足够大,它最终会耗尽熵,因此随机数的质量最终会略微降低。通常情况下,这仍然是足够好的,在这种情况发生之前还需要一段时间,但这是需要注意的事情(大多数人不需要关心,但可能可以接受,取决于你做了什么)。

read / write是线程安全的(只要它们不会崩溃或损坏数据或将描述符保留在未定义的状态)并且在这种特殊情况下不应该混合/在不同进程的读/写之间分配字节。但是,一般情况下,read / write 不保证此。他们可能在某些设备上混合并发读/写数据。

然而,它不应该是一个问题,因为如果你得到一些其他的随机位,而其他人在中间得到一些(不同的)位,则随机位仍然是随机的。
如果您认为这对您来说是一个问题,请使用readv 保证严格的原子性(无需混合/混合)。进出readv / writev的任何内容都将作为一个原子单元处理(管道上的除外,当超过PIPE_BUF的大小时,罗德里戈指出。

答案 1 :(得分:2)

读取是线程安全的,因为它是一个系统调用,如果你从多个线程进行多次读取,每次读取都将被串行处理。也就是说线程A将读取M个字节,线程B将读取下一个M字节,依此类推,而不是线程A读取几个字节,线程B读取几个字节,然后线程A读取更多字节。

写作也是如此。

多个线程执行读写操作的常见问题是,它们通常一次读/写1个字符,所以有很多机会混淆输入输入和输出来自 - 并经常混淆被存在于读/写

之上的语言运行库库添加