So rufen Sie das unterbrochene System in Linux auf

So rufen Sie das unterbrochene System in Linux auf

Vorwort

Langsame Systemaufrufe beziehen sich auf Systemaufrufe, die möglicherweise nie zurückkehren und den Prozess somit für immer blockieren. Beispielsweise sind „Accept“ (Akzeptieren), wenn keine Client-Verbindung besteht, und „Read“ (Lesen), wenn keine Eingabe erfolgt, beides langsame Systemaufrufe.

Wenn unter Linux ein Prozess, der in einem langsamen Systemaufruf blockiert ist, ein Signal erfasst, wird der Systemaufruf unterbrochen und stattdessen die Signalverarbeitungsfunktion ausgeführt. Dies ist der unterbrochene Systemaufruf.

Wenn die Signalverarbeitungsfunktion jedoch zurückkehrt, können die folgenden Situationen auftreten:

  • Wenn die Signalverarbeitungsfunktion bei Signal registriert ist, wird der Systemaufruf automatisch neu gestartet und die Funktion kehrt nicht zurück.
  • Wenn die Signalverarbeitungsfunktion mit sigaction registriert ist
    • Standardmäßig wird der Systemaufruf nicht automatisch neu gestartet, die Funktion gibt einen Fehler zurück und errno wird auf EINTR gesetzt
    • Der Systemaufruf wird nur dann automatisch neu gestartet, wenn das Flag SA_RESTART des Interruptsignals gültig ist.

Als Nächstes schreiben wir Code, um die oben genannten Situationen jeweils zu überprüfen, in denen der Systemaufruf „Lesen“ auswählt, das Unterbrechungssignal „SIGALRM“ auswählt und das Unterbrechungssignal durch einen Alarm generiert wird.

Signal verwenden

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

void-Handler (int s)
{
  printf("Lesen wird durch Signalhandler unterbrochen\n");
  zurückkehren;
}

int main()
{
  char Puffer[10];
  int nread = 0;

  Signal (SIGALRM, Handler);
  Alarm(2);

  printf("Lesestart\n");
  nread = lesen(STDIN_FILENO, buf, sizeof(buf));
  printf("lesen return\n");

  wenn ((nread < 0) und (errno == EINTR))
  {
    printf("Leserückgabe fehlgeschlagen, Fehlernummer ist EINTR\n");
  }

  gebe 0 zurück;
} 

Verwenden Sie Sigaction + Standard

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

void-Handler (int s)
{
  printf("Lesen wird durch Signalhandler unterbrochen\n");
  zurückkehren;
}

int main()
{
  char Puffer[10];
  int nread = 0;
  Struktur, Signatur, Akt;

  sigempyset(&act.sa_mask);
  act.sa_handler = Handler;
  act.sa_flags = 0; //Setzen Sie das SA_RESTART-Flag für das SIGALRM-Signal nicht und verwenden Sie die Standardverarbeitungsmethode von Sigaction //act.sa_flag |= SA_INTERRUPT; //SA_INTERRUPT ist die Standardverarbeitungsmethode von Sigaction, d. h. der unterbrochene Systemaufruf wird nicht automatisch neu gestartet. //Tatsächlich wird Sigaction gemäß SA_INTERRUPT verarbeitet, solange SA_RESTART nicht gesetzt ist, unabhängig vom Wert von act.sa_flags sigaction(SIGALRM, &act, NULL);
  Alarm(2);

  printf("Lesestart\n");
  nread = lesen(STDIN_FILENO, buf, sizeof(buf));
  printf("lesen return\n");

  wenn ((nread < 0) und (errno == EINTR))
  {
    printf("Leserückgabe fehlgeschlagen, Fehlernummer ist EINTR\n");
  }

  gebe 0 zurück;
} 


Verwenden Sie Sigaction + geben Sie das Flag SA_RESTART an

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

void-Handler (int s)
{
  printf("Lesen wird durch Signalhandler unterbrochen\n");
  zurückkehren;
}

int main()
{
  char Puffer[10];
  int nread = 0;
  Struktur, Signatur, Akt;

  sigempyset(&act.sa_mask);
  act.sa_handler = Handler;
  act.sa_flags = 0;
  act.sa_flags |= SA_RESTART; //Setze das SA_RESTART-Flag für das SIGALRM-Signal sigaction(SIGALRM, &act, NULL);
  Alarm(2);

  printf("Lesestart\n");
  nread = lesen(STDIN_FILENO, buf, sizeof(buf));
  printf("lesen return\n");

  wenn ((nread < 0) und (errno == EINTR))
  {
    printf("Leserückgabe fehlgeschlagen, Fehlernummer ist EINTR\n");
  }

  gebe 0 zurück;
} 


Aufgrund der Unterschiede in der Behandlung unterbrochener Systemaufrufe ergeben sich für Anwendungen im Zusammenhang mit unterbrochenen Systemaufrufen folgende Probleme:

  • Die Anwendung kann nicht immer wissen, wie der Signalhandler registriert wurde und ob das SA_RESTART-Flag gesetzt ist.
  • Portabler Code muss Fehlerrückgaben von Schlüsselfunktionen explizit behandeln. Wenn eine Funktion fehlschlägt und errno gleich EINTR ist, können Sie entsprechend darauf reagieren, z. B. indem Sie die Funktion neu starten.
int nread = lesen(fd, buf, 1024);

wenn (Anzahl der gelesenen Zahlen < 0)
{
  wenn (errno == EINTR)
  {
    //Der Lesevorgang wird unterbrochen, was nicht als Fehler angesehen werden sollte. Sie können entsprechend Ihren tatsächlichen Anforderungen damit umgehen, z. B. indem Sie den Leseaufruf neu schreiben oder ihn ignorieren.}
  anders
  {
    //den tatsächlichen Lesefehler lesen}
}

Zusammenfassen

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM.

Das könnte Sie auch interessieren:
  • Abrufen des Systemaufrufs und der Parameter eines Prozesses unter Linux (Fehlerbehebungsfall)
  • Detaillierte Analyse des Unterschieds zwischen Bibliotheksfunktionen und Systemaufrufen in Linux C
  • Detaillierte Analyse des Unterschieds zwischen Linux-Systemaufrufen und Standardbibliotheksaufrufen
  • Drei Möglichkeiten zum Implementieren von Linux-Systemaufrufen
  • Methode basierend auf Linux-Systemaufruf – Funktionen getrlimit() und setrlimit()
  • Detaillierte Erklärung des Linux-Systemaufrufprinzips
  • Hinweise zum Systemaufruf des Linux-Kernel-Gerätetreibers

<<:  MySQL-Konfiguration SSL-Master-Slave-Replikation

>>:  React antd realisiert dynamische Vergrößerung und Verkleinerung der Form

Artikel empfehlen

So setzen Sie das Root-Passwort in mysql8.0.12 zurück

Wenn Sie nach der Installation der Datenbank das ...

So richten Sie Spring Boot mithilfe der Docker-Schichtenverpackung ein

Das Spring Boot-Projekt verwendet Docker-Containe...

js implementiert zufälligen Namensaufruf

In diesem Artikel wird der spezifische Code von j...

So verwenden Sie js zur Kommunikation zwischen zwei HTML-Fenstern

Szenario: Wenn Seite A Seite B öffnet, muss Seite...

Ungewöhnliche, aber nützliche Tags in Xhtml

Xhtml hat viele Tags, die nicht häufig verwendet w...

Gründe, warum MySQL-Abfragen langsam sind

Inhaltsverzeichnis 1. Wo ist die Langsamkeit? 2. ...

Vuex in einem Artikel verstehen

Inhaltsverzeichnis Überblick Die vier Hauptobjekt...

Detaillierte Erläuterung der Verwendung der Vue3-Statusverwaltung

Inhaltsverzeichnis Hintergrund Bereitstellen / In...

Detaillierte Konfiguration der drahtlosen Netzwerkkarte unter Ubuntu Server

1. Stecken Sie die WLAN-Karte ein und prüfen Sie ...

JavaScript verwendet setTimeout, um einen Countdown-Effekt zu erzielen

Um die Fähigkeit zum Schreiben von nativem JavaSc...

MySQL-Techniken zum schnellen Datenvergleich

Im MySQL-Betrieb und bei der Wartung möchte ein F...

MySQL hilft Ihnen, Index-Pushdown in Sekunden zu verstehen

Inhaltsverzeichnis 1. Das Prinzip der Index-Push-...