[LINUX] Unterschied zwischen Vordergrundprozess und Hintergrundprozess, prinzipiell verstanden

Kannst du nicht im Hintergrund laufen?

Wissen Sie plötzlich, warum die Verarbeitung auf einem Unix-ähnlichen Gerät Folgendes bewirkt? Gibt es auch eine Möglichkeit, dies zu verhindern?

python


$ top &
[1] 11424
$ jobs -l
[1]+11424 gestoppt(Terminalausgang)         top

Wenn Sie mit dem Betriebssystem in der Shell arbeiten, hören Sie häufig die Begriffe Hintergrund- und Vordergrundprozesse.

Wenn Sie Ingenieur sind, haben Sie wahrscheinlich noch nichts davon gehört, und Sie kennen wahrscheinlich den Unterschied, aber Sie hatten wahrscheinlich nicht viel Gelegenheit, ihn systematisch zu verstehen. ??

Ursprünglich schrieb ich einen Artikel mit der Absicht, über den Daemon-Prozess in Qiita zu posten, aber aufgrund der Art des Daemon-Prozesses muss ich den Hintergrundprozess erwähnen und habe einen Eintrag mit der Erklärung gemacht. Ich dachte, es wäre kompliziert, also konzentrierte ich mich diesmal auf den Hintergrundprozess.

Das Obige ist das Verhalten, wenn die Programmoberseite im Hintergrund ausgeführt wird. top ist ein Programm, das Systemressourcen in Echtzeit überwacht. Wenn Sie es jedoch im Hintergrund ausführen, wird der Prozess sofort gestoppt. Das liegt natürlich daran, dass es implementiert ist, aber warum hört es auf?

Was ist überhaupt ein Hintergrundprozess? Und was ist ein Vordergrundprozess?

Lassen Sie uns zunächst den Unterschied zwischen dem Hintergrundprozess und dem Vordergrundprozess klären.

Vordergrund- und Hintergrundprozesse

Normalerweise sollte der vom Benutzer gestartete Prozess von der Shell gestartet (gegabelt) werden (in diesem Fall unter der Annahme der Befehlszeilenschnittstelle). Wenn Sie also den Terminaltreiber von einem Peripheriegerät wie einer Tastatur aus verwenden, "Strg + C" Sie können den Vorgang von SIGINT durch Eingabe benachrichtigen. Der über SIGINT gemeldete Prozess wird in den meisten Situationen abhängig von der Implementierung beendet.

Die Prozessgruppe, die bereit ist, Eingaben vom Terminal auf diese Weise zu akzeptieren, wird als Vordergrundprozessgruppe bezeichnet, und alle anderen Prozessgruppen, die nicht als Hintergrundprozessgruppe bezeichnet werden.

Alternativ wird es einfach als Vordergrundprozess oder Hintergrundprozess bezeichnet.

Dieser Unterschied ist etwas verwirrend, aber wenn Sie allgemein sagen, dass Sie etwas im Hintergrund tun möchten, bedeutet dies oft, dass der Vordergrundprozess eine Shell ist. Es gibt viele Fälle, weil es Fälle gibt, in denen dies nicht der Fall ist.

Lassen Sie uns ein Programm erstellen, um den Status zu überprüfen.

python


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

int main (int c, char *argv[]) {

    for (;;){
        fputs("test\n", stdout);
        //0 is file descriptor associated with the streams stdin.
        printf("stdin is %d\n", (int)tcgetpgrp(0));
        //1 is file descriptor associated with the streams stdout.
        printf("stdout is %d\n", (int)tcgetpgrp(1));
        sleep(5);
    }   

    return EXIT_SUCCESS;
}

Die Funktion tcgetpgrp verwendet einen Dateideskriptor als Argument und ruft die Prozessgruppen-ID des entsprechenden Vordergrundprozesses ab. Dieses Mal übergeben wir die Deskriptoren für Standardeingabe- und Standardausgabedateien.

Informationen zum Dateideskriptor finden Sie unter [Hacken des Linux-Dateideskriptors], das ich zuvor geschrieben habe.

python


$ ./a.out

Führen Sie die kompilierte ausführbare Datei im Vordergrund aus. Das Starten im Vordergrund ist nur eine Frage des Laufens.

python


test
stdin is 10455
stdout is 10455
test
stdin is 10455
stdout is 10455

Anschließend werden der Zeichenkettentest und die Prozess-ID der Vordergrundprozessgruppe des Terminals, auf die in der Standardeingabe und Standardausgabe verwiesen wird, auf dem Bildschirm angezeigt.

Da dieser Prozess in der Software keine Beendigungsbedingung aufweist, wird er nicht für immer beendet, es sei denn, ein Signal wie SIGINT wird dem Prozess von außen mitgeteilt.

Wenn Sie mit ps -jf f prüfen,

python


UID        PID  PPID  PGID   SID  C STIME TTY      STAT   TIME CMD
tajima   10360 10359 10360 10360  0 21:55 pts/1    Ss     0:00 -bash
tajima   10455 10360 10455 10360  0 22:25 pts/1    S+     0:00  \_ ./a.out

Da die laufende PGID 10455 ist, wissen wir, dass ./a.out der Vordergrundprozess ist. Mit anderen Worten, es ist möglich, Signale vom Terminal an den ./a.out-Prozess zu benachrichtigen, einzugeben und auszugeben.

Ich habe als Testversion "Strg + C" über die Tastatur eingegeben, und als ich SIGINT benachrichtigte, endete es.

Lassen Sie es uns jetzt im Hintergrund ausführen.

python


$ ./a.out &

Wenn Sie am Ende & hinzufügen, führt die Shell das Zielprogramm im Hintergrund aus.

python


test
stdin is 10360
stdout is 10360
test
stdin is 10360
stdout is 10360

Natürlich hat sich die Prozessgruppen-ID geändert, aber es ist keine Übertreibung zu sagen, dass dies mit dem Ausführen eines Programms im Vordergrund auf dem Display identisch ist.

Wenn Sie mit ps -jf f prüfen,

python


UID        PID  PPID  PGID   SID  C STIME TTY      STAT   TIME CMD
tajima   10360 10359 10360 10360  0 21:55 pts/1    Ss+    0:00 -bash
tajima   10460 10360 10460 10360  0 22:52 pts/1    S      0:00  \_ ./a.out

Da die PGID der terminalen Vordergrundprozessgruppe 10360 war, wissen wir, dass die Bash (Shell) der Vordergrundprozess ist. Und Sie können sehen, dass ./a.out der Hintergrundprozess ist. Mit anderen Worten, es ist möglich, Signale vom Terminal aus zu benachrichtigen und in den Bash-Prozess einzugeben.

Wenn Sie versuchen, "Strg + C" über die Tastatur einzugeben und SIGINT zu benachrichtigen, wird es so angezeigt, als ob es für einen Moment beendet wäre. Aber bald

python


test
stdin is 10360
stdout is 10360
test
stdin is 10360
stdout is 10360

Wird endlos wiederholt.

Dies liegt daran, dass das vorherige Strg + C benachrichtigt wurde, um zu schlagen, nicht um ./a.out.

Um diesen Prozess zu einem Vordergrundprozess zu machen, dh um die Ein- / Ausgabe des Terminals mit ./a.out zu verknüpfen, suchen Sie die Jobnummer mit dem in der Shell (bash) integrierten Befehl jobs und suchen Sie diese Nummer in fg. Wechseln Sie mit in den Vordergrund. Der Prozess wird übrigens vom Betriebssystem verwaltet, der Job jedoch von der laufenden Shell.

python


$ jobs
[1]Laufen./a.out &
$ fg %1

Wenn Sie tun

python


test
stdin is 10460
stdout is 10460
test
stdin is 10460
stdout is 10460

Wie Sie sehen können, hat sich die Prozessgruppen-ID des Vordergrundprozesses in ./a.out geändert.

Wie ändert sich also intern der Status des Prozesses, wenn der Hintergrundprozess von fg in den Vordergrund gedrängt wird?

Zuvor habe ich erklärt, dass die Funktion tcgetpgrp eine Funktion zum Abrufen der Prozessgruppen-ID des Vordergrundprozesses ist. Im Gegenteil, es gibt auch eine API namens tcsetpgrp, die das dem Dateideskriptor entsprechende Terminal als bestimmte Prozessgruppe angibt. Es hat die Aufgabe, es in der ID festzulegen.

Schreiben wir Code, der den Vordergrundprozess ohne Hilfe der Shell in einen Hintergrundprozess verwandelt.

Der Punkt ist, dass die Prozessgruppen-ID der Shell die Prozess-ID im Vordergrund sein sollte.

Ermitteln Sie zunächst die Prozessgruppen-ID der aktuellen Shell.

python


 PID  PGID   SID TTY      STAT   TIME COMMAND
15243 15243 15243 pts/1    Ss     0:00 -bash
25023 25023 15243 pts/1    R+     0:00  \_ ps -j f

Beachten Sie dies, da die PGID 15243 lautet.

python


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

int main (int c, char *argv[]) {

    for (;;){
        fputs("test\n", stdout);
        //0 is file descriptor associated with the streams stdin.
        printf("stdin is %d\n", (int)tcgetpgrp(0));
        //1 is file descriptor associated with the streams stdout.
        printf("stdout is %d\n", (int)tcgetpgrp(1));
        sleep(5);

        if (tcsetpgrp(0, 15243) < 0) {
            perror("tcsetpgrp() for stdin error");
        }   
        if (tcsetpgrp(1, 15243) < 0) {
            perror("tcsetpgrp() for stdout error");
        }   
    }   

    return EXIT_SUCCESS;

Wenn ich es einfach so mache, frage ich mich, ob der Vordergrund den Prozess nach 5 Sekunden in einen Hintergrundprozess verwandelt, aber es funktioniert nicht.

Wenn ein Prozess, der nach dem Erfolg von tcsetpgrp zu einem Hintergrundprozess wurde, versucht, über fputs in das Terminal zu schreiben, wird ein Signal SIGTTOU gesendet. Dieses Standardverhalten besteht jedoch darin, dass der Prozess gestoppt wird, weil der Prozess gestoppt wird. Weil es gemacht wird.

python


$jobs -l
[1]+29669 gestoppt(Terminalausgang)         ./a.out

Es gibt jedoch noch einen weiteren kleinen Grund, dies zu erklären, auf den ich später noch eingehen werde.

Top Hintergrundausführung

Hier ist die Erklärung für die erste Frage.

Lassen Sie uns die erste Frage noch einmal betrachten. Versuchen Sie, den Befehl top im Hintergrund auszuführen, um den aktuellen Systemstatus zu verstehen.

python


$ top &

Wenn Sie den Status des Prozesses in diesem Status überprüfen,

jobs -l
[1]+6432 gestoppt(Terminalausgang)         top

Sie können sehen, dass es vom Terminalausgang gestoppt wurde. Dies bedeutet, dass die SIGTTOU-Benachrichtigung den Prozess gestoppt hat.

Lassen Sie uns den Quellcode von top überprüfen.

top.c3342-3363



int main (int dont_care_argc, char *argv[])
{
   (void)dont_care_argc;
   before(*argv);
   windows_stage1();                    //                 top (sic) slice
   configs_read();                      //                 > spread etc, <
   parse_args(&argv[1]);                //                 > lean stuff, <
   whack_terminal();                    //                 > onions etc. <
   windows_stage2();                    //                 as bottom slice
                                        //                 +-------------+
                                        //                 +-------------+
   signal(SIGALRM,  end_pgm);
   signal(SIGHUP,   end_pgm);
   signal(SIGINT,   end_pgm);
   signal(SIGPIPE,  end_pgm);
   signal(SIGQUIT,  end_pgm);
   signal(SIGTERM,  end_pgm);
   signal(SIGTSTP,  suspend);
   signal(SIGTTIN,  suspend);
   signal(SIGTTOU,  suspend);
   signal(SIGCONT,  wins_resize_sighandler);
   signal(SIGWINCH, wins_resize_sighandler);

Dies geschieht innerhalb einer Funktion namens whack_terminal innerhalb der Hauptfunktion.

top.c1932-1954


static void whack_terminal (void)
{
   struct termios newtty;

   if (Batch) {
      setupterm("dumb", STDOUT_FILENO, NULL);
      return;
   }
   setupterm(NULL, STDOUT_FILENO, NULL);
   if (tcgetattr(STDIN_FILENO, &Savedtty) == -1)
      std_err("failed tty get");
   newtty = Savedtty;
   newtty.c_lflag &= ~(ICANON | ECHO);
   newtty.c_oflag &= ~(TAB3);
   newtty.c_cc[VMIN] = 1;
   newtty.c_cc[VTIME] = 0;

   Ttychanged = 1;
   if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtty) == -1) {
      putp(Cap_clr_scr);
      std_err(fmtmk("failed tty set: %s", strerror(errno)));
   }
   tcgetattr(STDIN_FILENO, &Rawtty);

Dies wird durch die Ausführung einer Funktion namens tcsetattr verursacht, die den Attributwert des Terminals ändert. Wenn diese Funktion als Hintergrundprozess ausgeführt wird, sendet SIGTTOU den Prozess und die Ausführung wird angehalten.

Wenn Sie beispielsweise den Quellcode von top wie unten gezeigt ändern und kompilieren, erhalten Sie einen Befehl top, der auch im Hintergrund kontinuierlich ausgeführt werden kann.

top.c1932-1954


int main (int dont_care_argc, char *argv[])
{
   signal(SIGTTOU, SIG_IGN);
   signal(SIGTTIN, SIG_IGN);
   (void)dont_care_argc;
   before(*argv);
   windows_stage1();                    //                 top (sic) slice
   configs_read();                      //                 > spread etc, <
   parse_args(&argv[1]);                //                 > lean stuff, <
   whack_terminal();                    //                 > onions etc. <
   windows_stage2();                    //                 as bottom slice
                                        //                 +-------------+
                                        //                 +-------------+
   signal(SIGALRM,  end_pgm);
   signal(SIGHUP,   end_pgm);
   signal(SIGINT,   end_pgm);
   signal(SIGPIPE,  end_pgm);
   signal(SIGQUIT,  end_pgm);
   signal(SIGTERM,  end_pgm);
   signal(SIGTSTP,  suspend);
   //signal(SIGTTIN,  suspend);
   //signal(SIGTTOU,  suspend);
   signal(SIGCONT,  wins_resize_sighandler);
   signal(SIGWINCH, wins_resize_sighandler);

Es weist den Prozess einfach an, die Signale SIGTTOU und SIGTTIN zu ignorieren, und kommentiert die Ausführung des Signal-Handler-Suspend aus. Wenn Sie in diesem Zustand oben bauen,

python


$ top &

Der Status der Systemressourcen wird regelmäßig asynchron ohne Unterbrechung an die Standardausgabe ausgegeben. Ich denke nicht, dass es im Allgemeinen praktisch ist, aber ich mag es, wenn ich es unendlich oben nenne. Wenn Sie interessiert sind, versuchen Sie es bitte.

Übrigens wird im Allgemeinen ein anderer Fall angenommen, in dem der Hintergrundprozess stoppt, wenn das Terminal bereit ist, Eingaben zu akzeptieren. SIGTTIN wird hier benachrichtigt, aber sein Standardverhalten ist der gleiche Prozessstopp wie bei SIGTTOU. Lassen Sie uns dies auch mit einem einfachen Beispielcode überprüfen.

input.c


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

int main (int argc, char *argv[]) {

    char a[10];

    if (fgets(a, sizeof(a), stdin) == NULL) {
        fprintf(stderr, "invalid input string.\n");
        exit(EXIT_FAILURE);
    }   

    a[strlen(a)-1] = '\0';

    printf("%s\n", a); 

    return EXIT_SUCCESS;
}

Führen Sie dies im Hintergrund aus.

python


$ ./a.out &

Wenn ich den Status des Prozesses überprüfe,

python


$ jobs -l
[1]+6490 gestoppt(Klemmeneingang)         ./a.out

Es wird durch Klemmeneingang (SIGTTIN) wie gestoppt.

Lassen Sie uns SIGTTOU mit einem einfachen Programm für alle Fälle überprüfen. Im obigen oberen Beispiel habe ich erklärt, dass die Benachrichtigung von SIGTTOU an Hintergrundprozesse dazu führt, dass der Prozess gestoppt wird. Dies sollte also der Fall sein.

out.c


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

int main (int argc, char *argv[]) {

    char a[10] = "test";

    for (;;) {
        printf("%s\n", a); 
        sleep(3);
    }   

    return EXIT_SUCCESS;
}

Wenn ich dieses Programm im Hintergrund starte,

python


$ ./a.out &
test
test
jobs -l
[1]+6562 läuft./a.out &

Der Prozess läuft und stoppt nicht. Was bedeutet das?

Tatsächlich ist SIGTTOU nicht so einfach wie SIGTTIN und erfordert Einstellungen, die in die Steuerinformationen des Terminaltreibers eingehen.

Die Verarbeitungsgruppe des Kernels, die den Datenfluss zwischen dem Prozess und dem externen Terminal steuert, wird als Terminaltreiber (tty-Treiber) bezeichnet, und das Verhalten in Bezug auf SIGTTOU ändert sich abhängig von der Einstellung dieses Terminaltreibers.

Sie können die aktuellen Terminaleinstellungen mit dem Befehl stty überprüfen.

python


$ stty
speed 9600 baud; line = 0;
eol = M-^?; eol2 = M-^?;
-brkint ixany
-echok

Abhängig von der Umgebung wird SIGTTOU nur dann an den Prozess gesendet, wenn das Programm im Hintergrund ausgeführt wird, wenn in dieser Einstellung das Flag "Anhalten" gesetzt ist.

Gehen Sie wie folgt vor, um den Stopp mit dem vorherigen Befehl einzustellen.

python


$ stty tostop
$ stty
speed 9600 baud; line = 0;
eol = M-^?; eol2 = M-^?;
-brkint ixany
-echok tostop

Eine Einstellung namens tostop wurde hinzugefügt. Versuchen Sie in diesem Zustand, das vorherige Programm auszuführen.

python


$ ./a.out &
jobs -l
[1]+11236 gestoppt(Terminalausgang)         ./a.out

Auf diese Weise wird der Prozess im Gegensatz zu zuvor gestoppt, indem der Ausgang zum Terminal erkannt wird. In einer Umgebung, in der das Topstop-Flag von Anfang an gesetzt ist, sollten Sie daher bestätigen können, dass es während der Hintergrundausführung ohne spezielle Einstellungen am Ausgang des Terminals stoppt.

Um die Einstellung mit dem Befehl stty abzubrechen, fügen Sie vor dem Flaggennamen ein.

python


$ stty -tostop
$ stty
speed 9600 baud; line = 0;
eol = M-^?; eol2 = M-^?;
-brkint ixany
-echok

Jetzt legen wir es im Programm fest, ohne stty zu verwenden.

out2.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <signal.h>

int main (int argc, char *argv[]) {

    struct termios newtty, oldtty;

    if (tcgetattr(1, &oldtty) == -1) {
        fprintf(stderr, "tcgetattr() failed.\n");
        exit(EXIT_FAILURE);
    }   

    newtty = oldtty;
    newtty.c_lflag |= TOSTOP;

    if (tcsetattr(1, TCSAFLUSH, &newtty) == -1) {
        fprintf(stderr, "tcsetattr() failed.\n");
        exit(EXIT_FAILURE);
    }

    char a[10] = "test";

    for (;;) {
        printf("%s\n", a);
        sleep(3);
    }

    return EXIT_SUCCESS;
}

Der Terminaltreiber wird unter Verwendung eines Datentyps namens Termios-Struktur eingestellt und erfasst. Dieser Code ähnelt dem Einstellungsteil des zuvor eingeführten Top-Codes, aber ich denke, es ist einfacher zu verstehen, warum der Hintergrundprozess aufgrund der Ausgabe an das Terminal gestoppt wurde.

Der Punkt ist, dass nach dem Abrufen der aktuellen Terminaltreibereinstellungen das TOSTOP-Flag darauf gesetzt und der Terminaltreiber erneut gesetzt wird.

Bash Mods

Übrigens konnte ich aufgrund der Benachrichtigung von SIGTTOU keinen gewaltsamen Hintergrundprozess aus einem Vordergrundprozess erstellen, daher werde ich bash ändern.

Die Operation ist je nach Shell unterschiedlich, aber im Fall von Bash wird die Signalsteuerungsverarbeitung im folgenden Teil durchgeführt.

jobs.c1904-1910



 void
 default_tty_job_signals ()
 {
   set_signal_handler (SIGTSTP, SIG_DFL);
   set_signal_handler (SIGTTIN, SIG_DFL);
   set_signal_handler (SIGTTOU, SIG_DFL);
 }

Ändern Sie daher den Prozess beim Erstellen eines untergeordneten Prozesses wie folgt.

jobs.c1762-1767


       if (pipeline_pgrp == shell_pgrp)
         ignore_tty_job_signals ();
       else
         default_tty_job_signals ();                                        
         
       set_signal_handler (SIGTTOU, SIG_IGN);  

Setzen Sie set_signal_handler (SIGTTOU, SIG_IGN) hier herum und erstellen Sie bash. Da SIGTTIN und SIGTSTP diesmal nicht besonders relevant sind, wird Ignorieren nicht angegeben.

Dadurch kann der zuvor gestoppte Prozess im gestoppten Vordergrund gestartet und dann im Hintergrund ausgeführt werden. Die Eingabe vom Terminal erreicht den gestarteten Prozess nicht.

Da die Eingabe und Ausgabe vom Terminal jedoch nicht den gestarteten Prozess erreichen, kann nicht gesagt werden, dass er ausschließlich im Hintergrund ausgeführt wird, aber der Hauptunterschied zwischen Vordergrund- und Hintergrundausführung besteht darin Ich denke du verstehst.

Um es vollständig zu implementieren, müssen Sie verstehen, wie die Jobsteuerung funktioniert, aber ich möchte es auch separat untersuchen.

Dieses Mal näherten wir uns dem Vordergrundprozess und dem Hintergrundprozess. Basierend auf diesen werde ich mich das nächste Mal dem Daemon-Prozess nähern.

Referenzierter Quellcode

proc-Befehle: procps-3.2.8 GNU bash, version 4.1.2 Die CPU ist x86_64.

OS CentOS release 6.8

Compiler

gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-17)

Recommended Posts

Unterschied zwischen Vordergrundprozess und Hintergrundprozess, prinzipiell verstanden
Was ist der Unterschied zwischen "pip" und "conda"?
Über den Unterschied zwischen "==" und "is" in Python
Über den Unterschied zwischen PostgreSQL su und sudo
Was ist der Unterschied zwischen Unix und Linux?
Berücksichtigung des Unterschieds zwischen ROC-Kurve und PR-Kurve
Grober Unterschied zwischen Unicode und UTF-8 (und seinen Begleitern)
Kann BERT den Unterschied zwischen "Ame (Süßigkeiten)" und "Ame (Regen)" verstehen?
Was ist der Unterschied zwischen usleep, nanosleep und clock_nanosleep?
Wie man Argparse benutzt und den Unterschied zwischen Optparse
Was ist der Unterschied zwischen symbolischen und harten Links?
Unterschied zwischen Prozess und Job
Unterschied zwischen "categoryical_crossentropy" und "sparse_categorical_crossentropy"
Verstehen Sie den Unterschied zwischen der kumulativen Zuordnung zu Variablen und der kumulativen Zuordnung zu Objekten
Unterschied zwischen Regression und Klassifikation
Unterschied zwischen np.array und np.arange
Unterschied zwischen MicroPython und CPython
Unterschied zwischen ps a und ps -a
Unterschied zwischen Return und Print-Python
Ich untersuchte das Verhalten bezüglich des Unterschieds zwischen Hard Link und Symbolic Link
Unterschied zwischen Ruby und Python Split
Unterschied zwischen Java und Python (Memo)
Unterschied zwischen list () und [] in Python
Unterschied zwischen SQLAlchemy filter () und filter_by ()
Unterschied zwischen == und ist in Python
Memorandum (Unterschied zwischen csv.reader und csv.dictreader)
(Hinweis) Unterschied zwischen Gateway und Standard-Gateway
Unterschied zwischen sortiert und sortiert (Denkmal)
[Python] Unterschied zwischen Funktion und Methode
Unterschied zwischen SQLAlchemy flush () und commit ()
Python - Unterschied zwischen exec und eval
[Python] Unterschied zwischen randrange () und randint ()
[Python] Unterschied zwischen sortiert und sortiert (Colaboratory)
[Einführung in Python] Was ist der Unterschied zwischen einer Liste und einem Taple?
[Xg Boost] Unterschied zwischen Softmax und Softprob
[Django ORM] Unterschied zwischen Werten () und nur ()
Unterschiede in der Beziehung zwischen PHP und Python schließlich und beenden
Unterschied zwischen @classmethod und @staticmethod in Python
Unterschied zwischen Anhängen und + = in der Python-Liste
Unterschied zwischen nicht lokal und global in Python
Unterschied zwischen linearer Regression, Ridge-Regression und Lasso-Regression
[Python] Unterschied zwischen Klassenmethode und statischer Methode
Java-Kompilierung und Ausführung von CLI verstanden
Unterschied zwischen Docker-Compose-Datei env_file und .env-Datei
Die subtile Beziehung zwischen Gentoo und Pip
[Python Iroha] Unterschied zwischen Liste und Tupel
[Python] Unterschied zwischen Rand- und Randn-Ausgabe
Geschwindigkeitsunterschied zwischen wsgi, Flasche und Flasche
Unterschied zwischen numpy.ndarray und list (Dimension, Größe)
Unterschied zwischen ls -l und cat Befehl
Differenz- und Kompatibilitätsprüfung zwischen Keras und tf.keras # 1