AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 563203
Accepted
ceving
ceving
Asked: 2020-01-22 05:03:49 +0800 CST2020-01-22 05:03:49 +0800 CST 2020-01-22 05:03:49 +0800 CST

dd 的 bs 参数的最大值是多少?

  • 772

我想写一个 CGI,它必须从 STDIN 读取指定数量的字节。我的想法是这样做:

dd bs=$CONTENT_LENGTH count=1

但我想知道,块大小是否受 RAM 以外的任何限制。

$ dd bs=1000000000000
dd: memory exhausted by input buffer of size 1000000000000 bytes (931 GiB)

GNU 的 coreutils 的手册页没有指定任何限制。

dd
  • 3 3 个回答
  • 8596 Views

3 个回答

  • Voted
  1. Best Answer
    Stephen Kitt
    2020-01-22T05:33:23+08:002020-01-22T05:33:23+08:00

    POSIX 规范dd没有明确指定最大值,但有一些限制:

    • 用于存储给定值的数据类型可以预期为,因为这是给定函数size_t要读取的字节数的类型;read
    • read还指定有一个限制SSIZE_MAX;
    • 在 Linux 下,无论如何read只能传输 2,147,479,552 字节。

    在 64 位平台上,size_t长度为 64 位;此外,它是无符号的,因此dd当给定值大于 2 64 – 1 时会失败:

    $ dd if=/dev/zero of=/dev/null bs=18446744073709551616
    dd: invalid number: ‘18446744073709551616’
    

    在 64 位 x86 上的 Linux 上,SSIZE_MAX是 0x7fffffffffffffffL(运行echo SSIZE_MAX | gcc -include limits.h -E -检查),这就是输入限制:

    $ dd if=/dev/zero of=/dev/null bs=9223372036854775808
    dd: invalid number: ‘9223372036854775808’: Value too large for defined data type
    
    $ dd if=/dev/zero of=/dev/null bs=9223372036854775807
    dd: memory exhausted by input buffer of size 9223372036854775807 bytes (8.0 EiB)
    

    一旦找到一个可以接受的值,下一个限制就是可以分配的内存量,因为dd需要先分配一个缓冲区,然后才能读入它。

    一旦找到可以分配的值,您将达到read限制(在 Linux 和其他具有类似限制的系统上),除非您使用 GNUdd并指定iflag=fullblock:

    $ dd if=/dev/zero of=ddtest bs=4294967296 count=1
    0+1 records in
    0+1 records out
    2147479552 bytes (2.1 GB, 2.0 GiB) copied, 38.3037 s, 56.1 MB/s
    

    (dd复制不到 2 31个字节,即上面提到的 Linux 限制,甚至不到我要求的一半)。

    正如上面链接的问答中所解释的,fullblock在任何情况下,对于任何bs大于 1 的值,您都需要可靠地复制所有输入数据。

    • 23
  2. Matteo Italia
    2020-01-22T16:15:08+08:002020-01-22T16:15:08+08:00

    不管它的最大值是多少,那里都有一个更大的问题;来自 POSIX 规范:

    该dd实用程序应将指定的输入文件复制到指定的输出文件,并使用特定的输入和输出块大小进行可能的转换。它应使用指定的输入块大小一次读取一个输入块;然后它将处理实际返回的数据块,该数据块可能小于请求的块大小。

    (重点补充)

    正如我过去写的,dd是一个非常愚蠢的工具:在你的情况下,它基本上归结为

    char *buf = malloc(bs);
    for(int i = 0; i < count; ++i) {
        int len = read(STDIN_FILENO, buf, bs);
        if(len == 0) break;
        write(STDOUT_FILENO, buf, len);
    }
    free(buf);
    

    bs只是dd用于执行read(2)系统调用的参数,但read(2)允许执行“短读取”,即返回的字节数少于请求的字节数。事实上,如果它现在有一些可用的字节,它就是这样做的,即使它们不是你所要求的全部;如果输入文件是 tty、管道或套接字,这很典型(因此您的 CGI 尤其处于危险之中......)。试试看嘛:

    $ dd bs=1000 count=1
    asd
    asd
    0+1 records in
    0+1 records out
    4 bytes copied, 1.75356 s, 0.0 kB/s
    

    在这里我输入asd并按下回车;dd读它(演奏一首read(STDIN_FILENO, buf, 1000)并写出来;它read按要求做了一个,所以它退出了。它看起来不像复制了 1000 个字节。

    归根结底,dd对于大多数需求来说,简单的“标准”是一种过于愚蠢的工具。您可以通过以下任一方式对其进行处理以执行您需要的操作:

    • 通过使用bs=1和使用count字节数;这可以保证复制您需要的字节数(如果在 EOF 之前可用),但效率很低,因为它每个字节执行一个系统调用;
    • 添加fullblock标志;这确保dd在写出之前累积一个完整的输入块。但是请注意,这是非标准的(GNU dd 有,IDK 有关于其他的)。

    最终,如果您要进行非 POSIX 扩展,我的建议是使用head -c: 它将做正确的事情,具有合理的缓冲并且没有特定的大小限制,确保正确性和良好的性能。

    • 6
  3. Eduardo Trápani
    2020-01-22T06:19:07+08:002020-01-22T06:19:07+08:00

    最大值取决于系统(包括其分配策略)和当前可用的内存。

    而不是一次尝试读取所有内容(您可能会耗尽内存,由于交换而减慢速度,您必须添加检查以查看它是否真的有效......)您可以使用dd.

    假设您想读取这些字节并将它们放入文件中。在 bash 中,你可以运行这样的东西(总字节数以 $total 为单位):

    block=65535
    count=$(expr $total / $block)
    rest=$(expr $total % $block)
    (dd bs=$block count=$count;dd bs=$rest count=1) > filename
    
    • 2

相关问题

  • 如何将磁盘归零+之后进行验证?[关闭]

  • 从大文件末尾删除空字节

  • dd 命令写入 /dev/sdc 改变了磁盘的大小

  • 确定两个 iso 图像是否相等

  • 如何在 macOS High Sierra 上加速 dd?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve