Pourquoi ne lit-il pas à partir de / dev / zero comme IO_RBYTES?

25

Je vide un disque dur sur un système d'exploitation Linux 4.x à l'aide de cette commande:

sudo sh -c 'pv -pterb /dev/zero > /dev/sda'

Et j'ai ouvert un autre tty et j'ai commencé sudo htopet remarqué ceci:

  PID USER      PRI  NI CPU%   RES   SHR   IO_RBYTES   IO_WBYTES S   TIME+  Command
 4598 root       20   0 15.5  1820  1596        4096    17223823 D  1:14.11 pv -pterb /dev/zero

La valeur de IO_WBYTESsemble tout à fait normale, mais IO_RBYTESreste à 4 Ko et ne change jamais.

J'ai exécuté quelques autres programmes, par exemple

dd if=/dev/zero of=/dev/zero
cat /dev/zero > /dev/zero

et a été surpris de voir qu'aucun d'entre eux ne génère beaucoup de IO_RBYTESou IO_WBYTES.

Je pense que cela n'est spécifique à aucun programme, mais pourquoi ne lit-il pas /dev/zeroet n'écrit-il pas pour /dev/{zero,null}compter comme octets d'E / S?

iBug
la source
5
Je suis curieux, pourquoi pensez-vous qu'ils devraient compter comme E / S?
marcelm
1
@marcelm Je pense que toute entrée / sortie devrait compter comme E / S, y compris les fichiers R / W, les E / S réseau et bien d'autres.
iBug
mais ces opérations effectuent des E / S sur le matériel (disque et carte réseau, respectivement) et doivent voyager sur un bus d'E / S (comme PCI-express), qui peuvent tous être un goulot d'étranglement important. Écrit pour, disons, /dev/nullne pas finir par interfacer avec un tel matériel et ne pas obstruer les bus d'E / S. Poussé à l'extrême; les lectures / écritures dans / depuis la mémoire sont-elles également des E / S? Bien sûr, il n'y a pas de délimitation stricte pour ces choses, et tout dépend de la perspective que vous adoptez dans ces choses, et de l'utilité de cette perspective pour vous.
marcelm
1
Remarque, mon premier commentaire avait pour but de vous inciter (et d'autres) à réfléchir à ces perspectives et à découvrir pourquoi vous adoptez votre point de vue. Je ne veux pas insinuer que vous vous trompez; Je ne pense même pas que la situation soit aussi noire et blanche. Mais personnellement, je serais beaucoup plus intéressé par les statistiques d'E / S sur le matériel réel (qui peut très bien être un goulot d'étranglement) que sur /dev/{null,zero}(qui n'est généralement pas un goulot d'étranglement). C'est juste mon point de vue cependant :)
marcelm
1
@marcelm Mais je pensais au départ que tout read(2)et write(2)compte comme des E / S, ce qui est très raisonnable dans son propre sens.
iBug

Réponses:

54

Ils comptent comme des E / S, mais pas du type mesuré par les champs que vous regardez.

Dans htop, IO_RBYTESet IO_WBYTESaffichez les champs read_byteset write_bytesde /proc/<pid>/io, et ces champs mesurent les octets qui traversent la couche de bloc. /dev/zeron'implique pas la couche de blocs, donc les lectures ne s'affichent pas là-bas.

Pour voir les E / S depuis /dev/zero, vous devez regarder les champs rcharet wchardans /proc/<pid>/io, qui apparaissent dans htopcomme RCHARet WCHAR:

rchar : lecture des caractères

Le nombre d'octets que cette tâche a provoqué pour être lu à partir du stockage. Il s'agit simplement de la somme des octets vers lesquels ce processus est passé read(2)et des appels système similaires. Il inclut des éléments tels que les E / S du terminal et n'est pas affecté par la nécessité ou non des E / S de disque physique réelles (la lecture peut avoir été satisfaite à partir de la mise en cache).

wchar : caractères écrits

Le nombre d'octets que cette tâche a provoqué ou doit faire écrire sur le disque. Des mises en garde similaires s'appliquent ici comme avec rchar.

Voir man 5 procet man 1 htoppour plus de détails.

Stephen Kitt
la source
C'est donc rcharet wcharqui comptent les octets des appels vers read(2)et write(2), non?
iBug
Oui c'est vrai.
Stephen Kitt
9
Parlez de phrasé trompeur sur la description de rchar . Tout ce qui est passé read()n'est certainement pas "lu depuis le stockage "!
ilkkachu
2
@ilkkachu storagesignifie "toute ligne de bus imaginable", que le stockage en question soit physique ou virtuel ou mmap'd ou une socket virtuelle ou dans le cache L1 - c'est juste n'importe quoi en dehors de la mémoire mappée de ce programme, y compris partagée
cat