【问题标题】:Block Linux read(2) until all of count bytes have arrived阻止 Linux read(2) 直到所有计数字节都到达
【发布时间】:2012-09-20 08:43:57
【问题描述】:

我正在使用read (2) 从文件中读取数据(/dev/random,其中数据到达非常缓慢)。

但是,read() 仅在读取几个字节后返回,而我希望它等待直到读取指定数量的字节(或发生错误),因此返回值应始终为 count,或 -1。

有没有办法启用这种行为? open (2)read (2) 联机帮助页不包含有关该主题的任何有用信息,我也没有在 Internet 上找到有关该主题的任何信息。

我完全了解将read() 放入while 循环并调用它直到读取所有数据的解决方法。我只想知道这是否可以通过产生确定性行为并且仅涉及 O(1) 系统调用的适当方式来实现,而不是在 while 循环解决方案的情况下使用非确定性 O(n)。

以下最小示例重现了该问题。

#include <stdio.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main() {
        int fd = open("/dev/random", 0);

        char buf[128];
        size_t bytes = read(fd, buf, sizeof(buf));

        printf("Bytes read: %lu\n", bytes); //output is random, usually 8.

        close(fd);
}

【问题讨论】:

    标签: c linux file system-calls blocking


    【解决方案1】:

    虽然读取可以在接收到请求的数据之前被信号中断,但如果没有 while 就无法真正完成。

    不幸的是,您必须检查返回值和字节数。 是的,最简单的方法是编写一个包装函数。

    【讨论】:

    • +1 并且因为这是/dev/random 无论如何......一些额外的读取调用不会减慢您的速度。
    【解决方案2】:

    正如大家所说,

    • 无法保证在您的读取返回之前有 128 个字节的随机性可用,并且

    • 与生成 8 个字节的摊销成本相比,一次获取 8 个字节的开销是微不足道的;因此,

    • 您应该记住,熵需要付出巨大的代价,并在消耗它时考虑到这一点。

    尽管如此,如果不注意在man 4 random(在一个模糊的最近的 Linux 发行版上)你应该找到以下信息,那么这个问题的答案是不完整的:

    The files in the directory /proc/sys/kernel/random
    (present since 2.3.16) provide an additional interface
    to the /dev/random device.
    

    ...

    The file read_wakeup_threshold contains the number of bits of
    entropy required for waking up processes that sleep waiting
    for entropy from /dev/random. The default is 64.
    

    即64个,也就是8个字节。使用超级用户权限,您可以增加此值,但恕我直言,将其增加到 1024,然后期望您的机器继续正常工作可能是相当乐观的。我不知道所有需要一点熵的东西,但我当然注意到我的熵池会上下波动,所以我知道有些东西想要它,我强烈怀疑无论是什么东西都不会高兴不得不等待它的 1024 位可用。无论如何,你知道有一点绳子......

    【讨论】:

      【解决方案3】:

      根据文档,/dev/random 尽最大努力返回最可靠的随机数据,这限制了它在一次读取中返回的字节数。

      但读取 /dev/urandom(注意“u”)将返回与您请求的数据一样多的数据(缓冲区大小),有时随机数据较少。

      这里是an useful link

      关于 read() 行为,我很确定这无法更改:read() 返回底层管道(例如磁盘+驱动程序+...)决定返回的数据量,这是一个由-设计行为。正如您所说,做事的方法是循环直到您收到与预期一样多的数据。

      【讨论】:

      • 这可靠吗? read可以被信号打断,源的类型能保证在通话结束前没有这样的信号到达吗?
      • 我需要真正的随机数据。另外,我认为不能保证从/dev/urandom 读取总是会读取count 字节,它只是更有可能。
      • 我认为是的,这是有保证的。无论如何,如果您希望数据尽可能随机,则必须使用 /dev/random AND 循环,直到达到您想要的字节数。很抱歉,但我真的,真的认为你不能强制 read() 返回尽可能多的数据。
      • 是的,urandom 理论上不像random 那样随机;-)
      猜你喜欢
      • 1970-01-01
      • 2016-02-11
      • 1970-01-01
      • 1970-01-01
      • 2021-06-10
      • 2019-10-04
      • 2015-07-04
      • 1970-01-01
      • 2021-07-30
      相关资源
      最近更新 更多