Tamanho do arquivo do dispositivo (ausente na saída ls -l)

4

Quando tento imprimir, a saída do arquivo do dispositivo mostra dados binários em formato hexadecimal. Mas ao fazer um ls -l /dev/sda eu recebo:

brw-rw----  1 root disk      8,   0 Jan 29 12:29 /dev/sda

Eu não entendo qual é o tamanho real do arquivo? O que esses números significam?

    
por Abhishek Bhatia 30.01.2016 / 23:43

3 respostas

3

TL; DR : é assim que os desenvolvedores implementaram o ls.c . Dependendo do tipo de arquivo, a string de saída para a opção longa -l será criada de forma diferente. A documentação do GNU não menciona a diferença de formato (veja a nota lateral sobre a página de manual do OpenBSD).

Arquivos de dispositivos e código-fonte ls

/dev/sda é um dispositivo de bloco (explicado mais adiante na seção). É diferente do arquivo normal. ls.c constrói a longa cadeia de saída de acordo com o tipo de arquivo em que está trabalhando. Como mostrado abaixo, para dispositivos de bloco, nada sobre o tamanho é anexado à string de saída!

ls.c tem as seguintes linhas de código:

   3757 static void
   3758 print_long_format (const struct fileinfo *f)
   3759 {

( partially omited )

   3868   if (f->stat_ok
   3869       && (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode)))
   3870     {
   3871       char majorbuf[INT_BUFSIZE_BOUND (uintmax_t)];
   3872       char minorbuf[INT_BUFSIZE_BOUND (uintmax_t)];
   3873       int blanks_width = (file_size_width
   3874                           - (major_device_number_width + 2
   3875                              + minor_device_number_width));
   3876       sprintf (p, "%*s, %*s ",
   3877                major_device_number_width + MAX (0, blanks_width),
   3878                umaxtostr (major (f->stat.st_rdev), majorbuf),
   3879                minor_device_number_width,
   3880                umaxtostr (minor (f->stat.st_rdev), minorbuf));
   3881       p += file_size_width + 1;
   3882     }
   3883   else
   3884     {
   3885       char hbuf[LONGEST_HUMAN_READABLE + 1];
   3886       char const *size =
   3887         (! f->stat_ok
   3888          ? "?"
   3889          : human_readable (unsigned_file_size (f->stat.st_size),
   3890                            hbuf, file_human_output_opts, 1,
   3891                            file_output_block_size));
   3892       int pad;
   3893       for (pad = file_size_width - mbswidth (size, 0); 0 < pad; pad--)
   3894         *p++ = ' ';
   3895       while ((*p++ = *size++))
   3896         continue;
   3897       p[-1] = ' ';
   3898     }

Observe que, se filetype for S_ISCHR (dispositivo de caractere, fluxo contínuo de dados) ou S_ISBLK (dispositivo de bloco, acesso aleatório), os números maior e menor do dispositivo serão impressos na matriz de caracteres p (que é essencialmente um corda). Esses são os únicos dados anexados à string de saída p . No entanto, quando chegarmos a else part, ls entenderá que estamos trabalhando com arquivos diferentes de dispositivos de bloco ou de caractere . Para esses arquivos, ele atribui dados armazenados em matriz de tamanho aos próximos segmentos da matriz p size (que é while ((*p++ = *size++)) part).

A idéia principal é que eu saiba em que tipo de arquivo ele está olhando e constrói a saída de acordo

O que são arquivos de dispositivos mesmo assim?

Essencialmente, são referências. Eles são uma maneira de os aplicativos lidarem com dispositivos físicos reais e seus drivers. Por exemplo, /dev/sda e /dev/sr0 (que é a unidade de CD / DVD). Alguns dos dispositivos são apenas abstração. Por exemplo, /dev/zero , /dev/null e /dev/random não são dispositivos físicos. São formas de interagir com os processos do kernel.

Como são referências, faz sentido que elas não tenham tamanho de arquivo . É possível saber o tamanho desses arquivos que eles ocupam no diretório /dev , mas eles não correspondem aos dispositivos reais que eles representam!

Assim, é compreensível que ls.c desenvolvedores implementaram o código dessa maneira. O tamanho do arquivo das referências é 99,99% dos tempos não necessários por qualquer motivo.

Mas os dispositivos de bloco, pelos quais normalmente nos referimos a discos rígidos e drives USB, são dispositivos físicos, com tamanho físico real, então como podemos descobrir isso?

Descobrir o tamanho dos dispositivos de bloco reais

Os métodos abaixo ilustram como se pode descobrir o tamanho de um disco rígido / ssd / USB referenciado por um dispositivo de bloco em '/ dev /

  • lsblk ou lsblk /dev/sda
  • sudo blockdev --getsize64 /dev/sda
  • sudo fdisk -l /dev/sda ou sudo fdisk -l para todos os devs
  • sudo parted /dev/sda print ou sudo parted -l para todos os devs
  • awk '{print *512}' /sys/class/block/sda/size
  • awk '{=*1024;print}' /proc/partitions ou awk ' == "sda1" {=*1024;print}' /proc/partitions para partições específicas.

Notas laterais

  • /proc/devices contém lista de todos os números principais que correspondem aos dispositivos de bloco
  • Os comandos du , stat e find podem mostrar o tamanho dessas referências, mas não são necessárias para a vida diária (se houver)
  • Existe diferença entre a representação de dispositivos de bloco; alguns arquivos implementam blocos de representação de 512 (como em /sys filesystem), enquanto outros - 1024 . Essa é uma convenção no mundo Unix / Linux, pois é assim que os blocos físicos reais dos discos rígidos são alocados.
  • Ao contrário da documentação do GNU ls , Página man do OpenBSD declara explicitamente:" Se o arquivo for especial de um caractere ou arquivo especial de bloco, os números de dispositivos maiores e menores do arquivo serão exibidos no campo de tamanho . " (grifo meu)

Referências

por Sergiy Kolodyazhnyy 31.01.2016 / 00:28
4

Não consigo encontrar nenhuma documentação de por que ls os mostra em vez de 0 como du ou stat , mas, como Byte Commander diz, eles são os números dos dispositivos maiores e menores daquele arquivo especial. Da origem :

if (f->stat_ok
  && (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode)))
{
  char majorbuf[INT_BUFSIZE_BOUND (uintmax_t)];
  char minorbuf[INT_BUFSIZE_BOUND (uintmax_t)];
  int blanks_width = (file_size_width
                      - (major_device_number_width + 2
                         + minor_device_number_width));
  sprintf (p, "%*s, %*s ",
           major_device_number_width + MAX (0, blanks_width),
           umaxtostr (major (f->stat.st_rdev), majorbuf),
           minor_device_number_width,
           umaxtostr (minor (f->stat.st_rdev), minorbuf));
  p += file_size_width + 1;
}

Este código, parte da a print_long_format() function , usado quando o formato de saída é longo (o que é com -l ), usa os números de dispositivo no lugar do tamanho para caractere e dispositivo de bloco.

Para obter o tamanho real do dispositivo, vários métodos estão listados em este Unix & amp; Postagem no Linux .

    
por muru 31.01.2016 / 00:28
3

Parece que você perdeu o conceito de 'tudo-é-um-arquivo'.

No mundo do UNIX tudo (dados, dispositivos, sockets, ..) é mapeado para um arquivo. Esses arquivos têm tipos - no caso do seu diretório home, você encontrará (principalmente) os chamados arquivos regulares (texto, programas, ...).

Em contraste com esses arquivos regulares, o / dev-directory mantém - implícito pelos arquivos de nome do dispositivo. Portanto, você encontrará arquivos do tipo c haracter, b lock e p ipe representando dispositivos, por exemplo. / dev / mem é um arquivo que representa sua memória de sistemas, / dev / ttyACM0 pode ser um modem serial. O link entre esses arquivos (device-) e os drivers responsáveis é criado usando os números maiores e menores, como mostrado por ls (e como explicado acima).

O tamanho de um dispositivo é um atributo específico do dispositivo e deve ser consultado usando ferramentas específicas do dispositivo (como mostrado na postagem acima) porque não há uma maneira única de lidar com esse atributo (um SSD pode ter um tamanho fixo - mas uma porta serial pode fornecer um fluxo interminável de dados para que não haja tamanho fixo, o / dev / null tem armazenamento infinito:)).

Você pode ler aqui: link

    
por hecke 31.01.2016 / 00:06