[LINUX] Ich verfolgte die Implementierung des Befehls du (erste Hälfte)

Einführung

du ist ein Befehl zum Anzeigen der Verzeichniskapazität. Wenn Sie es ohne Optionen verwenden, werden alle Verzeichniskapazitäten unter dem aktuellen Verzeichnis angezeigt. Dieses Mal werde ich die Implementierung verfolgen, um zu sehen, wie die Funktion realisiert wird.

Erwartet

Als Verhalten wäre es schön, wenn es eine Funktion gäbe, um das Verzeichnis zu verfolgen und die Dateigröße darin zu addieren. Dafür sind wahrscheinlich die folgenden Funktionen erforderlich.

  1. Befolgen Sie die Verzeichnisse und Dateien der Reihe nach
  2. Holen Sie sich die Dateigröße
  3. Summieren Sie die Dateigröße im Verzeichnis

Schauen wir uns die Implementierung an und konzentrieren uns darauf, wie diese Funktionen realisiert werden.

Folgen Sie der Implementierung

Dieses Mal werden wir uns den Quellcode von du.c ansehen, der in GNU coreutils enthalten ist. Die Hauptfunktion ruft du_files () auf.

python


/* Recursively print the sizes of the directories (and, if selected, files)
   named in FILES, the last entry of which is NULL.
   BIT_FLAGS controls how fts works.
   Return true if successful.  */

static bool
du_files (char **files, int bit_flags)
{
  bool ok = true;

  if (*files)
    {
      FTS *fts = xfts_open (files, bit_flags, NULL); //(1)

      while (1)
        {
          FTSENT *ent;

          ent = fts_read (fts); //(2)
          if (ent == NULL)
            {
              if (errno != 0)
                {
                  error (0, errno, _("fts_read failed"));
                  ok = false;
                }
              break;
            }
          FTS_CROSS_CHECK (fts);
          ok &= process_file (fts, ent); //(3)
        }

      if (fts_close (fts) != 0)
        {
          error (0, errno, _("fts_close failed"));
          ok = false;
        }
    }

  return ok;
}

Die hier durchgeführte Verarbeitung ist die folgenden drei.

(1). Holen Sie sich die FTS-Struktur aus dem Dateinamen mit xfts_open (). (2) Holen Sie sich die FTSENT-Struktur aus der FTS-Struktur mit fts_read (). (3) Rufen Sie "process_file ()" auf und kehren Sie zu (2) zurück.

xfts_open() "Xfts_open ()" in (1) ist ein Wrapper für "fts_open ()" und intern wird "fts_open ()" aufgerufen. Das an xfts_open () übergebene Argument ist der Dateiname. Dieser Dateiname wird durch das Befehlszeilenargument angegeben. Wenn kein Argument vorhanden ist, wird das aktuelle Verzeichnis übergeben. Die von xfts_open () erhaltene FTS-Struktur ist ein Handle der Dateihierarchie. Das Feld verfügt über eine FTSENT-Struktur, die Informationen zur Datei darstellt, sowie über die aktuelle Position und untergeordnete FTSENT-Strukturen. Jedes Mal, wenn Sie in (2) fts_read () aufrufen, ändern sie sich und folgen der Dateihierarchie (siehe unten).

fts_read() In (2) "fts_read ()" wird die FTSENT-Struktur an der aktuellen Position aus der FTS-Struktur erhalten. Die FTSENT-Struktur enthält die folgenden Felder (fts).

python


typedef struct _ftsent {
    unsigned short fts_info;     /*Flags für FTSENT-Strukturen*/
    char          *fts_accpath;  /*Zugriffspfad*/
    char          *fts_path;     /*Wurzelpfad*/
    short          fts_pathlen;  /* fts_Pfadlänge*/
    char          *fts_name;     /*Dateiname*/
    short          fts_namelen;  /* fts_Länge des Namens*/
    short          fts_level;    /*Tiefe(-1 〜 N) */
    int            fts_errno;    /*Datei Fehlernummer*/
    long           fts_number;   /*Lokale Nummer*/
    void          *fts_pointer;  /*Lokale Adressnummer*/
    struct ftsent *fts_parent;   /*Übergeordnetes Verzeichnis*/
    struct ftsent *fts_link;     /*Die folgende Dateistruktur*/
    struct ftsent *fts_cycle;    /*Zirkulierende Struktur*/
    struct stat   *fts_statp;    /* stat(2)Information*/
} FTSENT;

Die Dateigröße ist in fts_stap (stat).

python


struct stat {
    dev_t     st_dev;     /*ID des Geräts, auf dem sich die Datei befindet*/
    ino_t     st_ino;     /*Inode-Nummer*/
    mode_t    st_mode;    /*Zugangsschutz*/
    nlink_t   st_nlink;   /*Anzahl der Hardlinks*/
    uid_t     st_uid;     /*Benutzer-ID des Besitzers*/
    gid_t     st_gid;     /*Gruppen-ID des Besitzers*/
    dev_t     st_rdev;    /*Geräte ID(Für spezielle Dateien) */
    off_t     st_size;    /*Gesamte Größe(Byteeinheit) */
    blksize_t st_blksize; /*Dateisystem I./In O.
Block Größe*/
    blkcnt_t  st_blocks;  /*Anzahl der zugewiesenen 512B-Blöcke*/
};

Daher kann die Dateigröße erhalten werden, indem die Statistikstruktur aus der FTSENT-Struktur verfolgt wird.

Nun wurde die FTSENT-Struktur durch fts_read () in (2) erhalten. Da fts_read () automatisch der Dateihierarchie folgt, scheint es, dass der Befehl du implementiert werden kann, indem fts_read () wiederholt aufgerufen und die Dateigröße summiert wird. Der Vorgang der Summierung der Dateigröße erfolgt über "process_file ()" in (3).

Folgen Sie der Datei

Bevor wir uns nun mit der Erläuterung von (3) befassen, sehen wir uns an, wie die Dateihierarchie mit fts_read () verfolgt wird. Überprüfen Sie den Vorgang mit dem folgenden Code (Lesen Sie die ls von FreeBSD Lassen Sie uns ls mit fts (3) ~ machen).

python


#include <stdio.h>
#include <stdlib.h>
#include <fts.h>

int main (int argc, char *argv[])
{
        FTS *ftsp;
        FTSENT *p;
        static char dot[] = ".";
        static char *dotav[] = {dot, NULL};

        if (argc == 1)
                argv = dotav;
        else
                argv++;
        ftsp = fts_open(argv, 0, NULL);
        while((p = fts_read(ftsp)) != NULL) {
                printf("%s\n", p->fts_path);
        }
        fts_close(ftsp);

        exit(EXIT_SUCCESS);
}

Dieser Code ist eine Implementierung des Befehls ls mit der Funktion fts. Alle Dateien und Verzeichnisse unter dem Verzeichnis werden angezeigt. Das fts_read () in der while -Anweisung folgt der Dateihierarchie, und das p-> fts_path zeigt den Dateinamen an. Das Ausführungsergebnis ist wie folgt.

$ ./ls 
.
./dir1
./dir1/file3
./dir1/file4
./dir1/dir2
./dir1/dir2/file5
./dir1/dir2
./dir1
./ls.c
./ls
./file2
./file1
.

Die Anzeigereihenfolge ist wie folgt. dir.jpeg

Sie können sehen, dass die Tiefe priorisiert ist, die Datei einmal durchlaufen wird und das Verzeichnis zweimal durchlaufen wird.

Fortsetzung

Nächstes Mal wird der Prozess von process_file () in (3) angezeigt.

Recommended Posts

Ich verfolgte die Implementierung des Befehls du (erste Hälfte)
Ich verfolgte die Implementierung des Befehls du (zweite Hälfte)
Ich habe die Implementierung von range gelesen (Objects / rangeobject.c)
[Linux] Ich habe versucht, die Ressourcenbestätigungsbefehle zusammenzufassen
Erster Python 3 ~ Der Beginn der Wiederholung ~
Ich habe den Mechanismus der Flaschenanmeldung untersucht!
[Python] Ich habe die Theorie und Implementierung der logistischen Regression gründlich erklärt
[Python] Ich habe die Theorie und Implementierung des Entscheidungsbaums gründlich erklärt
Holen Sie sich das erste Element von Queryset
Ich brachte AI dazu, über die Texte von Genshi Yonezu nachzudenken (Implementierung)
Ich habe versucht, die häufig verwendete Implementierungsmethode von pytest-mock zusammenzufassen
Ich habe den Befehl worldcup verwendet, um das Ergebnis der Weltmeisterschaft zu überprüfen.
Ich möchte einen beliebigen Befehl im Befehlsverlauf von Shell belassen
Ich habe den Inhalt des Docker-Volumes überprüft
Ich habe den asynchronen Server von Django 3.0 ausprobiert
Ich habe versucht, den Befehl umask zusammenzufassen
Ich habe die Optionen von copyMakeBorder von OpenCV überprüft
Othello-Aus der dritten Zeile von "Implementation Deep Learning" (3)
Die Ordnerstruktur von Flask ist zusammengefasst
Ich kannte die Grundlagen von Python nicht
Migemo-Version des Befehls: find,: mfind
Die Python-Projektvorlage, an die ich denke.
Lesen Sie die Implementierung des globalen ARM-Timers
Beachten Sie den Abschluss eines zeitaufwändigen Befehls
AtCoder Rückblick auf frühere Fragen (erste Hälfte von 12 / 8,9)
Othello-Aus der dritten Zeile von "Implementation Deep Learning" (2)
Ich habe versucht, die Lernfunktion im neuronalen Netzwerk sorgfältig zu verstehen, ohne die Bibliothek für maschinelles Lernen zu verwenden (erste Hälfte).
Ich habe einen Appdo-Befehl erstellt, um Befehle im Kontext der App auszuführen
[Python] Ich habe die Theorie und Implementierung der Support Vector Machine (SVM) ausführlich erklärt.
Ich habe die Pivot-Table-Funktion von Pandas ausprobiert
Ich habe versucht, die Wetterkarte einer Clusteranalyse zu unterziehen
Ich habe das tiefste Problem von Hiroshi Yuki gelöst.
Warum die Python-Implementierung von ISUCON 5 Bottle verwendet
Ich habe zuerst die SARS-Analyse vor dem Corona-Virus versucht
Ich habe die Liste der Tastenkombinationen von Jupyter überprüft
Ich habe zum ersten Mal versucht, Python zu programmieren.
Ich habe versucht, die Trapezform des Bildes zu korrigieren
Probieren Sie Progate Free Edition [Python I]
Ich habe die Sitzungsaufbewahrungsdauer von Django überprüft
Die Geschichte des Fehlinterpretierens der Swap-Zeile des obersten Befehls
Ich habe die Verarbeitungsgeschwindigkeit der numpy eindimensionalisierung überprüft
Ich habe Mind Meld zum ersten Mal ausprobiert
Ich habe einige der neuen Funktionen von Python 3.8 touched angesprochen
Ich habe die Varianten von UKR gelesen und implementiert
Ich möchte das Erscheinungsbild von zabbix anpassen
Ich habe versucht, den Bildfilter von OpenCV zu verwenden
Ich habe versucht, die Texte von Hinatazaka 46 zu vektorisieren!
Zweite Hälfte des ersten Tages des Python-Studiums Versuchen Sie, die Twitter-API mit Bottle zu erreichen
[Erste Datenwissenschaft ⑥] Ich habe versucht, den Marktpreis von Restaurants in Tokio zu visualisieren
Ich habe mir den Inhalt von sklearn (scikit-learn) angesehen. (1) ~ Was ist mit der Implementierung von CountVectorizer? ~
Ich habe das TensorFlow-Tutorial mit Kommentaren ausgeführt (erstes neuronales Netzwerk: Beginn des Klassifizierungsproblems)
Ich möchte auch Linux-Befehle an der Eingabeaufforderung verwenden! Verwenden Sie Linux-Befehle an der Eingabeaufforderung anstelle von Git Bash