[LINUX] Was ist der Unterschied zwischen usleep, nanosleep und clock_nanosleep?

Einführung

Es gibt viele Schlaffunktionen in C-Sprache. Oft weiß ich nicht, wo ich was verwenden soll. Das heißt, Sie können kein echter C-Programmierer sein, wenn Sie die Schlaffunktion richtig wählen. C-Programmierer haben die Mission, das Beste aus vielen Optionen auszuwählen und eine konkurrenzlose Leistung zu liefern.

Lass den Witz beiseite

In diesem Artikel werde ich über den Unterschied zwischen usleep, nanosleep und clock_nanosleep schreiben, die eine hochpräzise Schlafverarbeitung realisieren können.

Die Zielversion des Linux-Kernels ist ** 5.4.2 **.

Erste Schlussfolgerung

Nach diesem Abschnitt werde ich den Quellcode des Linux-Kernels lesen, aber das weiß ich nicht. Für diejenigen, die schnell eine Schlussfolgerung ziehen möchten, schreibe ich zuerst die Schlussfolgerung.

Wie, diese drei Funktionen machen *** fast das gleiche Verhalten ***!

Nur clock_nanosleep kann sein Verhalten abhängig vom Argument ändern. Wenn Sie jedoch CLOCK_MONOTONIC als erstes Argument von clock_nanosleep übergeben, ist das Verhalten der drei Funktionen dasselbe.

Jede dieser Funktionen hat jedoch eine andere Verwendbarkeit. Es scheint am besten, eine Funktion zu verwenden, die in jeder Situation einfach aufzurufen ist. Wenn Sie sicherstellen möchten, dass sie auf Quellcodeebene übereinstimmen, lesen Sie die folgenden Abschnitte.

Was für eine Funktion ist das überhaupt?

Mal sehen, welche Funktionen usleep, nanosleep und clock_nanosleep sind. Diese Informationen stammen aus dem Linux-Programmierhandbuch des Menschen.

usleep usleep-Defer Ausführung in Mikrosekunden

#include <unistd.h>
int usleep(useconds_t usec);

nanosleep nanosleep-hochpräziser Schlaf

#include <time.h>
int nanosleep(const struct timespec *req, struct timespec *rem); 

clock_nanosleep clock_nanosleep - Präziser Stopp (Schlaf) bei der angegebenen Uhr

#include <time.h>
int clock_nanosleep(clockid_t clock_id, int flags,
                    const struct timespec *request,
                    struct timespec *remain);

Nun, was ich tun möchte, ist fast dasselbe. Ich möchte im Nanosekundenbereich schlafen.

Systemaufruf oder Bibliotheksfunktion

Als nächstes möchte ich jede Funktion nach Systemaufruf oder Bibliotheksfunktion klassifizieren. (Nun, Systemaufrufe bieten auch eine Schnittstelle auf der Bibliotheksseite, um den Assembler zu verpacken. Hier klassifizieren wir sie jedoch danach, ob sie als Linux-Kernel-Systemaufrufe definiert sind oder nicht.)

usleep nanosleep clock_nanosleep
Bibliotheksfunktion Systemaufruf Systemaufruf

Es sieht aus wie das.

Betrachten wir nun jede Funktion auf Quellcode-Ebene.

Lesen und sehen Sie den Quellcode

usleep

Schauen wir uns nun die Definition von usleep an.

usleep ist eine von glibc definierte Funktion und kein Linux-Systemaufruf. Sie können dann erwarten, dass usleep einen Systemaufruf aufruft, um in dieser Funktion zu schlafen. Als ich mir tatsächlich den Quellcode von glibc angesehen habe, war es wie folgt.

https://github.com/lattera/glibc/blob/master/sysdeps/posix/usleep.c

int
usleep (useconds_t useconds)
{
  struct timespec ts = { .tv_sec = (long int) (useconds / 1000000),
			 .tv_nsec = (long int) (useconds % 1000000) * 1000ul };

  /* Note the usleep() is a cancellation point.  But since we call
     nanosleep() which itself is a cancellation point we do not have
     to do anything here.  */
  return __nanosleep (&ts, NULL);
}

Wenn man sich diesen Quellcode und die Kommentare ansieht, scheint usleep den Aufruf des Nanosleep-Systems aufzurufen. Mit anderen Worten *** glibc "Ist es nicht mühsam, eine Zeitspezifikationsstruktur für das Argument von Nanosleep zu erstellen? Ich habe eine Wrapper-Funktion definiert." *** Es ist als solches definiert. Daher kann gesagt werden, dass usleep eine Funktion ist, die Mikrosekunden empfängt, eine darauf basierende Zeitspezifikationsstruktur erzeugt und schließlich den Nanosleep-Systemaufruf aufruft. Im Moment weiß ich, dass sich Usleep und Nanosleep ähnlich verhalten werden.

nanosleep Da nanosleep ein Linux-Systemaufruf ist, lesen wir den Quellcode des Linux-Kernels. nanosleep ist ein Systemaufruf /kernel/time/hrtimer.c line:1945 https://elixir.bootlin.com/linux/v5.4.2/source/kernel/time/hrtimer.c#L1945 ist.

SYSCALL_DEFINE2(nanosleep, struct __kernel_timespec __user *, rqtp,
		struct __kernel_timespec __user *, rmtp)
{
	struct timespec64 tu;

	if (get_timespec64(&tu, rqtp))
		return -EFAULT;

	if (!timespec64_valid(&tu))
		return -EINVAL;

	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
	current->restart_block.nanosleep.rmtp = rmtp;
	return hrtimer_nanosleep(&tu, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
}

Sie können endlich sehen, dass wir eine Funktion namens hrtimer_nanosleep aufrufen. Diese Funktion ist eine Funktion, die die Schlafverarbeitung mit einem hochpräzisen Timer namens High Resolution Timer ausführt. CLOCK_MONOTONIC wird an das dritte Argument der Funktion hrtimer_nanosleep übergeben. Oh, das hätte eine Konstante sein sollen, die auch an clock_nanosleep übergeben werden könnte. Nachdem ich etwas gerochen habe, werfen wir einen Blick auf die Implementierung des Systemaufrufs clock_nanosleep.

clock_nanosleep Lesen Sie abschließend den Quellcode von clock_nanosleep. Dieser Systemaufruf /kernel/time/posix-stubs.c line: 124 https://elixir.bootlin.com/linux/v5.4.2/source/kernel/time/posix-stubs.c#L124 Es ist definiert in.

SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
		const struct __kernel_timespec __user *, rqtp,
		struct __kernel_timespec __user *, rmtp)
{
	struct timespec64 t;

	switch (which_clock) {
	case CLOCK_REALTIME:
	case CLOCK_MONOTONIC:
	case CLOCK_BOOTTIME:
		break;
	default:
		return -EINVAL;
	}

	if (get_timespec64(&t, rqtp))
		return -EFAULT;
	if (!timespec64_valid(&t))
		return -EINVAL;
	if (flags & TIMER_ABSTIME)
		rmtp = NULL;
	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
	current->restart_block.nanosleep.rmtp = rmtp;
	return hrtimer_nanosleep(&t, flags & TIMER_ABSTIME ?
				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
				 which_clock);
}

Diese Funktion überprüft zuerst die angegebene Uhr-ID. Abgesehen von CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_BOOTTIME scheint ein Fehler aufzutreten. Nach dem Lesen von *** entspricht dies mit Ausnahme der Flags-Prüfung fast der Definition des Nanosleep-Systemaufrufs, den wir im vorherigen Abschnitt gesehen haben. *** ***

Die Beschreibung unterscheidet sich vorerst von Nanosleep

flags & TIMER_ABSTIME ?
                 HRTIMER_MODE_ABS : HRTIMER_MODE_REL

Ich werde diesen Teil auch kurz erklären. Flags sind Flags, die an den Systemaufruf clock_nanosleep übergeben werden können. Wenn dieses Flag auf *** TIMER_ABSTIME *** gesetzt ist, wird HRTIMER_MODE_ABS an die Funktion *** hrtimer_nanosleep *** übergeben, wenn dies nicht der Fall ist. Wenn gemäß der Beschreibung des Menschen das Flag *** TIMER_ABSTIME *** angegeben ist,

** Wenn flags TIMER_ABSTIME ist, wird das Argument rest nicht verwendet und wird nicht benötigt (das Anhalten bei einem absoluten Wert kann mit demselben Anforderungsargument erneut aufgerufen werden). ** ** **

ist das, was sie gesagt haben. Mit anderen Worten, ich habe festgestellt, dass dieser Prozess hinzugefügt wurde, um das Flag clock_nanosleep zu verarbeiten.

Fazit nach dem Lesen des Quellcodes

Ich habe die Schlussfolgerung oben gesagt, aber anscheinend verhalten sich diese drei Funktionen ähnlich. Mit anderen Worten, jede Methode ruft letztendlich die Funktion hrtimer_nanosleep auf, und der Prozess zum Bestimmen der Argumente, die an diese Funktion übergeben werden sollen, ist unterschiedlich. Wenn ich Sie zwinge, etwas zu verändern, denke ich, dass es diese Flexibilität ist. Obwohl usleep und nanosleep nur CLOCK_MONOTONIC als Sleep-Flag verwenden können, kann clock_nanosleep vom Programmierer frei entschieden werden.

abschließend

Die Schlussfolgerung war, dass es am Ende keinen großen Unterschied gab, aber eine Open-Source-Kultur war wesentlich, um zu dieser Schlussfolgerung zu gelangen. Als bestes Open Source hoffe ich, dass sich freie Software weiterentwickelt!

Recommended Posts

Was ist der Unterschied zwischen usleep, nanosleep und clock_nanosleep?
Was ist der Unterschied zwischen "pip" und "conda"?
Was ist der Unterschied zwischen Unix und Linux?
Was ist der Unterschied zwischen symbolischen und harten Links?
Über den Unterschied zwischen "==" und "is" in Python
[Einführung in Python] Was ist der Unterschied zwischen einer Liste und einem Taple?
Unterschied zwischen == und ist in Python
[Einführung in das Modell für Infektionskrankheiten] Was ist der Unterschied zwischen der April-Epidemie und dieser Epidemie? .. .. ‼
Die Antwort von "1/2" unterscheidet sich zwischen Python2 und 3
Über den Unterschied zwischen PostgreSQL su und sudo
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?
Wie man Argparse benutzt und den Unterschied zwischen Optparse
Unterschied zwischen Prozess und Job
Unterschied zwischen Regression und Klassifikation
[Python] Python und Sicherheit - is Was ist Python?
Unterschied zwischen np.array und np.arange
Unterschied zwischen MicroPython und CPython
Was ist die Schnittstelle für ...
Was ist die Rückruffunktion?
Unterschied zwischen ps a und ps -a
Unterschied zwischen Return und Print-Python
Verstehen Sie den Unterschied zwischen der kumulativen Zuordnung zu Variablen und der kumulativen Zuordnung zu Objekten
Unterschied zwischen SQL Alchemy back_populated und backref und wenn keiner verwendet wird
Unterschied zwischen Vordergrundprozess und Hintergrundprozess, prinzipiell verstanden
Unterschied zwischen Ruby und Python Split
Unterschied zwischen Java und Python (Memo)
Memorandum (Unterschied zwischen csv.reader und csv.dictreader)
[Python] Was ist @? (Über Dekorateure)
(Hinweis) Unterschied zwischen Gateway und Standard-Gateway
[Python] Was ist der sortierte Schlüssel?
Unterschied zwischen Numpys Randint und Randoms Randint
Unterschied zwischen sortiert und sortiert (Denkmal)
Unterschied zwischen der Python2-Serie und der Python3-Serie dict.keys ()
Was ist das X Window System?
Wofür ist der Python-Unterstrich (_)?
Ich untersuchte das Verhalten bezüglich des Unterschieds zwischen Hard Link und Symbolic Link
[Python] Unterschied zwischen Funktion und Methode
Unterschied zwischen SQLAlchemy flush () und commit ()
[Python] Inklusive Notation. Schreiben Sie eine einfache for-Anweisung. (Eine Sammlung ist der Unterschied zwischen einem iterierbaren und einem Iterator.)
Python - Unterschied zwischen exec und eval
[Python] Unterschied zwischen randrange () und randint ()
[Python] Unterschied zwischen sortiert und sortiert (Colaboratory)
[Xg Boost] Unterschied zwischen Softmax und Softprob
Unterschied zwischen Anweisungen (Anweisungen) und Ausdrücken (Ausdrücken) in Python
[Django ORM] Unterschied zwischen Werten () und nur ()
Unterschiede in der Beziehung zwischen PHP und Python schließlich und beenden
Was ist Clivoa, ein Framework für die ETL-Verarbeitung?
[Unix] Was ist der Zombie-Prozess / Orphan-Prozess?
Unterschied zwischen @classmethod und @staticmethod in Python
Was ist die Ursache für den folgenden Fehler?
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
Was ist "Mahjong" in der Python-Bibliothek? ??
[Python] Unterschied zwischen Klassenmethode und statischer Methode
Unterschied zwischen Docker-Compose-Datei env_file und .env-Datei
Die subtile Beziehung zwischen Gentoo und Pip
Über die Beziehung zwischen Git und GitHub