Heim  >  Artikel  >  System-Tutorial  >  Artefakt unter Linux: Prinzipien und Anwendungen von eventfd

Artefakt unter Linux: Prinzipien und Anwendungen von eventfd

王林
王林nach vorne
2024-02-13 20:30:16659Durchsuche

Linux ist ein leistungsstarkes Betriebssystem, das viele effiziente Mechanismen für die prozessübergreifende Kommunikation bereitstellt, wie z. B. Pipes, Signale, Nachrichtenwarteschlangen, gemeinsam genutzten Speicher usw. Aber gibt es eine einfachere, flexiblere und effizientere Art der Kommunikation? Die Antwort ist ja, das ist eventfd. eventfd ist ein Systemaufruf, der in Linux Version 2.6 eingeführt wurde. Er kann zur Implementierung von Ereignisbenachrichtigungen verwendet werden, d. h. zur Übermittlung von Ereignissen über einen Dateideskriptor. eventfd enthält einen vom Kernel verwalteten 64-Bit-Ganzzahlzähler ohne Vorzeichen. Der Prozess kann den Zählerwert lesen/ändern, indem er diesen Dateideskriptor liest/schreibt, um eine Kommunikation zwischen Prozessen zu erreichen. Was sind die Vorteile von eventfd? Es verfügt über folgende Funktionen:

Artefakt unter Linux: Prinzipien und Anwendungen von eventfd

  • eventfd muss keine zusätzlichen Dateien oder Speicherplatz erstellen, es benötigt nur einen Dateideskriptor
  • eventfd kann in Verbindung mit Multiplex-Mechanismen wie Select, Poll und Epoll verwendet werden, um eine effiziente ereignisgesteuerte Programmierung zu erreichen
  • eventfd kann auf den nicht blockierenden oder den Semaphor-Modus eingestellt werden und bietet so unterschiedliche Kommunikationssemantiken
  • eventfd kann Prozess- oder Threadgrenzen überschreiten, um unterschiedliche Kommunikationsebenen zu erreichen.

Also, wie funktioniert eventfd? Welche Anwendungsszenarien gibt es? In diesem Artikel wird das Artefakt eventfd aus zwei Aspekten vorgestellt: Prinzip und Anwendung.

Allgemein gesagt: Es gibt fünf Hauptlösungen für die prozessübergreifende Kommunikation unter Linux: Pipes, Nachrichtenwarteschlangen, Semaphoren, gemeinsam genutzter Speicher und Sockets.
Ich kenne mich nur mit den Einschränkungen allgemeiner Pipes und der Beziehung zwischen übergeordneten und untergeordneten Prozessen aus, da ich keine unabhängige Kommunikation zwischen Prozessen durchführen möchte auf übergeordnete und untergeordnete Prozesse beschränkt sein, aber im Kernel-Status nicht sicher, wie man es verwendet.
Ich verstehe Message Queue überhaupt nicht.
Der Kern des Semaphors ist eine atomare Operation von Kernelvariablen, aber die Schnittstelle spiegelt sich nur im Benutzerstatus wider, und die PV-Operation des Semaphors scheint eher ein gegenseitiger Ausschluss zu sein als der von mir gewünschte Benachrichtigungsweckmechanismus .
Noch problematischer ist die Schnittstelle im Benutzermodus. Wenn Sie den Speicher zwischen Kernelmodus und Benutzermodus teilen möchten, müssen Sie die Datei selbst schreiben und dann die mmap-Schnittstelle bereitstellen.
Sockets wurden bisher nur mit af_inets tcp/udp und af_unix's dgram verwendet. Der Kernel bietet zwar keine klare Schnittstelle, Sie können sie jedoch selbst aufrufen Schließlich müssen Sie die Eingabeparameter selbst erstellen, was sich immer noch unsicher anfühlt.

Das Einzige, was noch übrig ist, scheint Netlink zu sein. Dieser Socket stellt eindeutig die Paketsendefunktion des Kernels bereit, da er eindeutig die Funktion netlink_kernel_create exportiert, sodass die Kernel-Statusfunktion diesen Socken zum Senden von Paketen verwenden kann. Aber zum einen muss der Benutzermodus eine Paketempfangsfunktion registrieren, zum anderen muss der Kernelmodus immer noch skb zusammenstellen, um Pakete zu senden. Für mich, die einfach nur durch Benachrichtigung aufwachen möchte, ist das immer noch zu kompliziert.

Also habe ich erneut gesucht und das Artefakt eventfd zwischen KVM und Qemu gefunden. Nach sorgfältiger Analyse des Quellcodes habe ich festgestellt, dass dieses Ding nur für Benachrichtigungen geeignet ist .
Als Datei (gibt es unter Linux etwas, das keine Datei ist~~) hat ihre private_data-Struktur eventfd_ctx nur vier erbärmliche Variablen.

struct eventfd_ctx {
  struct kref kref;  /* 这个就不多说了,file计数用的,用于get/put */
  wait_queue_head_t wqh; /* 这个用来存放用户态的进程wait项,有了它通知机制才成为可能 */
/*
\* Every time that a write(2) is performed on an eventfd, the
\* value of the __u64 being written is added to "count" and a
\* wakeup is performed on "wqh". A read(2) will return the "count"
\* value to userspace, and will reset "count" to zero. The kernel
\* side eventfd_signal() also, adds to the "count" counter and
\* issue a wakeup.
*/
  __u64 count;  /* 这个就是一个技术器,应用程序可以自己看着办,read就是取出然后清空,write就是把value加上 */
  unsigned int flags;  /* 所有的file都有的吧,用来存放阻塞/非阻塞标识或是O_CLOEXEC之类的东西 */
};
  我之所以选用它是因为它有 eventfd_signal 这个特地为内核态提供的接口,下面的是注释。
 \* This function is supposed to be called by the kernel in paths that do not
 \* allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
 \* value, and we signal this as overflow condition by returining a POLLERR to poll(2).

Tatsächlich wird es klarer, wenn Sie sich den Code ansehen

int eventfd_signal(struct eventfd_ctx *ctx, int n)
{
  unsigned long flags;

  if (n return -EINVAL;
  spin_lock_irqsave(&ctx->wqh.lock, flags);
  if (ULLONG_MAX - ctx->count count);
  ctx->count += n;
  if (waitqueue_active(&ctx->wqh))
    wake_up_locked_poll(&ctx->wqh, POLLIN);
  spin_unlock_irqrestore(&ctx->wqh.lock, flags);

  return n;
}  

Die Essenz besteht darin, einmal aufzuwachen, ohne zu lesen oder zu schreiben. Der Unterschied zu eventfd_write besteht darin, dass es keine Blockierung gibt

Hier ist meine spezifische Verwendung:

Der Kernel-Status ist ein Modul, das ein anderes Gerät registriert und einen funktionierenden Kernel-Thread erstellt (der Parameter ist die Datei -> private_Daten des Moduls). Stellen Sie eine ioctl-Schnittstelle für den Benutzermodusprozess bereit, um den von seinem eigenen eventfd erstellten fd zu liefern und ihn in file->private_data zu speichern, auf den der Kernel-Thread zugreifen kann.
Wenn der Kernel-Status den Benutzerstatus benachrichtigen möchte, wird eventfd_signal direkt verwendet. Zu diesem Zeitpunkt muss sich der Benutzerstatus-Thread zuerst auf eventfd_ctx->wqh platzieren. Es gibt zwei Lösungen: Eine besteht darin, read aufzurufen, und die andere darin Umfrage aufrufen. Wenn es sich um einen Lesevorgang handelt, wird eventfd_ctx->count später gelöscht und kann beim nächsten Mal blockiert werden. Wenn poll jedoch verwendet wird, wird der Zähler danach nicht gelöscht, was dazu führt, dass poll sofort zurückkehrt, auch wenn beim erneuten Polling kein eventfd_signal im Kernel-Status vorhanden ist.
Es ist etwas aufwändiger, den Kernel-Status über den Benutzerstatus zu benachrichtigen. Zuerst müssen Sie ein EventFD erstellen und es dann an file->private_data senden (der Vorgang ist hier derselbe wie oben). Erstellen Sie ein iotcl im Modul, das für den Benutzerstatus verantwortlich ist, um den Kernelstatus zu benachrichtigen. Der Kernelstatusthread muss zuerst auf eventfd_ctx->wqh platziert werden eine Abfrage im Kernel-Status selbst durchführen (scheint wieder mühsam zu sein).

Dieser Artikel stellt eventfd vor, ein Artefakt in Linux. Es ist ein einfacher, flexibler und effizienter Kommunikationsmechanismus zwischen Prozessen. Wir haben die Erstellung, das Lesen und Schreiben sowie die Flag-Bits von eventfd unter prinzipiellen Aspekten analysiert und entsprechende Codebeispiele gegeben. Wir haben auch die Verwendung von eventfd in Szenarien wie Benutzermodus- und Kernelmodus-Kommunikation, Timern und Ereignisauslösern aus der Anwendungsperspektive vorgestellt und entsprechende Codebeispiele gegeben. Durch das Studium dieses Artikels können wir die grundlegende Verwendung von Eventfd beherrschen und Eventfd in der tatsächlichen Entwicklung flexibel verwenden, um unterschiedliche Kommunikationsanforderungen zu erfüllen. Ich hoffe, dieser Artikel ist hilfreich für Sie!

Das obige ist der detaillierte Inhalt vonArtefakt unter Linux: Prinzipien und Anwendungen von eventfd. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:lxlinux.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen