web-dev-qa-db-fra.com

Taille du fichier de périphérique (manquant dans la sortie ls -l)

Lorsque j'essaie d'imprimer le fichier de périphérique, la sortie affiche des données binaires au format hexadécimal. Mais en faisant un ls -l /dev/sda je reçois:

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

Je ne comprends pas quelle est la taille réelle du fichier? Que signifient ces chiffres?

4
Abhishek Bhatia

TL; DR : c'est ainsi que les développeurs ont implémenté le ls.c. En fonction du type de fichier, la chaîne de sortie pour l'option longue -l sera construite différemment. La documentation de GNU ne mentionne pas la différence de format (voir la note sur la page de manuel d'OpenBSD).

Fichiers de périphérique et code source ls

/dev/sda est un périphérique en mode bloc (expliqué plus loin dans cette section). C'est différent du fichier normal. ls.c construit la longue chaîne de sortie en fonction du type de fichier sur lequel elle travaille. Comme indiqué ci-dessous, pour les périphériques en mode bloc, rien sur la taille n'est ajouté à la chaîne de sortie!

ls.c a les lignes de code suivantes:

   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     }

Notez que si le type de fichier est S_ISCHR (périphérique de caractères, flux continu de données) ou S_ISBLK (périphérique de bloc, accès aléatoire), les numéros de périphérique majeur et mineur sont imprimés dans le tableau de caractères p (qui est essentiellement une chaîne). C'est la seule donnée ajoutée à la chaîne de sortie p. Cependant, lorsque nous arrivons à else part, ls comprend que nous travaillons avec des fichiers autres que des périphériques block ou character . Pour ces fichiers, il affecte les données stockées dans un tableau de taille aux segments suivants de ce tableau p size (c'est la partie while ((*p++ = *size++)).).

L'idée principale est que ls sait quel type de fichier il recherche et crée la sortie en conséquence

Qu'est-ce qu'un fichier de périphérique?

Ce sont essentiellement des références. Ils permettent aux applications de gérer des périphériques physiques réels et leurs pilotes. Par exemple, /dev/sda et /dev/sr0 (qui est un lecteur de CD/DVD). Certains des appareils ne sont que de l'abstraction. Par exemple, /dev/zero, /dev/null et /dev/random ne sont pas des périphériques physiques. Ce sont des moyens d'interfaçage avec les processus du noyau.

Puisqu'ils sont des références, il est logique qu'ils n'aient pas la taille du fichier . Il est possible de connaître la taille des fichiers qu’ils prennent dans le répertoire /dev, mais ils ne correspondent pas aux périphériques qu’ils représentent!

Il est donc compréhensible que les développeurs de ls.c implémentent le code de cette façon. La taille du fichier des références est 99,99% des fois inutile pour une raison quelconque.

Mais les périphériques de bloc, par lesquels on entend généralement les disques durs et les lecteurs USB, sont des périphériques physiques, avec une taille physique réelle, alors comment pouvons-nous savoir cela?

Recherche de la taille des périphériques en mode bloc

Les méthodes ci-dessous montrent comment déterminer la taille d’un disque dur/ssd/USB référencé par un périphérique bloc dans `/ dev /

  • lsblk ou lsblk /dev/sda
  • Sudo blockdev --getsize64 /dev/sda
  • Sudo fdisk -l /dev/sda ou Sudo fdisk -l pour tous les développeurs
  • Sudo parted /dev/sda print ou Sudo parted -l pour tous les développeurs
  • awk '{print $1*512}' /sys/class/block/sda/size
  • awk '{$3=$3*1024;print}' /proc/partitions ou awk '$4 == "sda1" {$3=$3*1024;print}' /proc/partitions pour des partitions spécifiques.

Notes annexes

  • /proc/devices contient la liste de tous les numéros principaux correspondant aux périphériques en mode bloc
  • Les commandes du, stat et find peuvent vous indiquer la taille de ces références, mais ne sont pas nécessaires dans la vie quotidienne (le cas échéant).
  • Il y a une différence entre la représentation des périphériques en mode bloc; certains fichiers implémentent des blocs de représentation de 512 (comme sous le système de fichiers /sys), tandis que d'autres - 1024 . C'est une convention dans le monde Unix/Linux, car c'est ainsi que sont alloués les blocs physiques réels sur les disques durs.
  • Contrairement à la documentation GNU ls, page de manuel OpenBSD indique explicitement: "Si le fichier est un caractère spécial ou un fichier spécial bloqué, les numéros de périphérique majeur et mineur du fichier sont affichés dans le champ de taille . " (italique ajouté par moi)

Références

3
Sergiy Kolodyazhnyy

Je ne trouve aucune documentation expliquant pourquoi ls les affiche à la place d'un simple 0 comme du ou stat, mais comme le dit Byte Commander, ils sont les numéros de périphérique majeur et mineur de ce fichier spécial. à partir de la source :

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;
}

Ce code, qui fait partie de la fonction print_long_format() , utilisé lorsque le format de sortie est long (qu’il soit avec -l), utilise les numéros de périphérique à la place de la taille pour caractère et dispositif de bloc.

Pour obtenir la taille réelle du périphérique, plusieurs méthodes sont répertoriées dans cet article Unix & Linux .

4
muru

Il semble que vous ayez raté le concept de "tout-est-un-fichier".

Dans le monde UNIX, tout (données, périphériques, sockets, ..) est mappé sur un fichier. Ces fichiers ont des types - dans le cas de votre répertoire personnel, vous trouverez (principalement) des fichiers dits classiques (texte, programmes, ...).

Contrairement à ces fichiers normaux, le répertoire/dev contient - ce qui est supposé par son nom - des fichiers de périphérique. Par conséquent, vous trouverez des fichiers de type c haracter, b verrouiller et p ipe représentant des périphériques, par exemple./dev/mem est un fichier qui représente la mémoire de votre système,/dev/ttyACM0 peut être un modem série. Le lien entre ces fichiers (périphérique) et les pilotes responsables est créé à l'aide des nombres majeur et mineur, comme indiqué par ls (et comme expliqué ci-dessus).

La taille d’un périphérique est un attribut spécifique et doit être interrogée à l’aide d’outils spécifiques (comme indiqué dans l’article ci-dessus), car il n’existe pas de moyen unique de traiter cet attribut (un disque SSD peut avoir une taille fixe, mais un port série). peut fournir un flux de données sans fin, il n’ya donc pas de taille fixe,/dev/null a un stockage infini :)).

Vous pouvez lire sur ici: https://en.wikipedia.org/wiki/Everything_is_a_file

3
hecke