AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 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

Qual é o valor máximo para o argumento bs de dd?

  • 772

Eu quero escrever um CGI, que deve ler um número especificado de bytes de STDIN. Minha ideia é fazer assim:

dd bs=$CONTENT_LENGTH count=1

Mas eu queria saber se o tamanho do bloco é limitado por qualquer outra coisa além da RAM.

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

A página de manual do coreutils do GNU não especifica nenhum limite.

dd
  • 3 3 respostas
  • 8596 Views

3 respostas

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

    As especificações POSIX paradd não especificam um máximo explicitamente, mas existem alguns limites:

    • pode-se esperar que o tipo de dados usado para armazenar o valor fornecido seja size_t, pois esse é o tipo do número de bytes a serem lidos fornecido à readfunção ;
    • readtambém é especificado para ter um limite de SSIZE_MAX;
    • no Linux, readapenas transfere até 2.147.479.552 bytes de qualquer maneira.

    Em uma plataforma de 64 bits, size_ttem 64 bits de comprimento; além disso, não é assinado, portanto dd, falhará quando forem fornecidos valores maiores que 2 64 – 1:

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

    No Linux em x86 de 64 bits, SSIZE_MAXé 0x7ffffffffffffffL (execute echo SSIZE_MAX | gcc -include limits.h -E -para verificar), e esse é o limite de entrada:

    $ 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)
    

    Depois de encontrar um valor que seja aceito, o próximo limite é a quantidade de memória que pode ser alocada, pois ddprecisa alocar um buffer antes de poder ler nele.

    Depois de encontrar um valor que pode ser alocado, você atingirá o readlimite (no Linux e outros sistemas com limites semelhantes), a menos que você use GNU dde especifiqueiflag=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
    

    ( ddcopiado pouco menos de 2 31 bytes, ou seja , o limite do Linux mencionado acima, nem metade do que eu pedi).

    Conforme explicado no link de perguntas e respostas acima, você precisará fullblockcopiar de forma confiável todos os dados de entrada em qualquer caso, para qualquer valor bsmaior que 1.

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

    Independentemente do seu valor máximo, aí você tem um problema maior; da especificação POSIX:

    O ddutilitário deve copiar o arquivo de entrada especificado para o arquivo de saída especificado com possíveis conversões usando tamanhos de bloco de entrada e saída específicos. Ele deve ler a entrada um bloco por vez, usando o tamanho do bloco de entrada especificado; ele deve então processar o bloco de dados realmente retornado, que pode ser menor que o tamanho do bloco solicitado.

    (enfase adicionada)

    Como escrevi no passado , ddé uma ferramenta extremamente estúpida: no seu caso, basicamente se resume a

    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é apenas o argumento ddusado para realizar a read(2)syscall, mas read(2)é permitido realizar uma "short read", ou seja, retornar menos bytes do que o solicitado. De fato, é o que ele faz se tiver alguns bytes disponíveis agora, mesmo que não sejam tudo o que você pediu; isso é típico se o arquivo de entrada for um tty, um pipe ou um socket (então você está particularmente em risco com seu CGI...). Apenas tente:

    $ 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
    

    Aqui eu digitei asde apertei enter; ddlê-lo (executando um single read(STDIN_FILENO, buf, 1000)e escrevê-lo; ele fez um readconforme solicitado, então ele sai. Não parece que ele copiou 1000 bytes.

    Em última análise, o "padrão" simples ddé uma ferramenta muito estúpida para a maioria das necessidades; você pode disputar para fazer o que você precisa:

    • usando bs=1e usando countpara o número de bytes; isso é garantido para copiar o número de bytes que você precisa (se disponível antes do EOF), mas é bastante ineficiente, pois executa uma syscall por byte;
    • adicione a fullblockbandeira; isso garante que ddacumule um bloco de entrada completo antes de escrevê-lo. Observe, no entanto, que isso não é padrão (GNU dd tem isso, IDK sobre outros).

    Por fim, se você estiver optando por uma extensão não POSIX, minha sugestão é apenas usar head -c: ele fará a coisa certa com buffer sensato e sem limites de tamanho específicos, garantindo correção e bom desempenho.

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

    O máximo depende do sistema (incluindo suas políticas de alocação) e da memória disponível no momento.

    Em vez de tentar ler tudo de uma vez (você poderia esgotar a memória, desacelerar as coisas por causa da troca, você teria que adicionar verificações para ver se realmente funcionava ...), você poderia ler blocos de tamanho razoável com dd.

    Digamos que você queira ler esses bytes e colocá-los em um arquivo. No bash, você pode executar algo assim (o total de bytes está em $ total):

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

relate perguntas

  • Como zerar um disco + verificar depois? [fechado]

  • Remover bytes nulos do final de um arquivo grande

  • O comando dd gravando em /dev/sdc mudou o tamanho do disco

  • Determine se duas imagens iso são iguais

  • Como acelerar o dd no macOS High Sierra?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

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

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve