Thread unter Linux anhalten (korrigierte Version am Ende des Artikels)

Da es unter Linux keine Suspend Thread-ähnliche API gab, versuchen Sie, den Thread mit Mutex anzuhalten / fortzusetzen.

Zur Zeit habe ich es zweimal implementiert, aber ich habe darauf hingewiesen, dass ich nicht zu viel Wissen über die Implementierung der OS-API habe, also habe ich es zweimal gegessen, also bin ich verrückt danach, also frage ich mich, ob es das dritte Mal ist, um ehrlich zu sein, oder ob es zwei Mal gibt.

Zusammenfassung der bisher zu beachtenden Punkte

Punkte von @drab

  1. Sie können "pthread_cond_wait" oder "fifo oder Nachrichtenwarteschlange" verwenden.
  2. Die Verwendung von pthread_cond_wait in Code, der etwas mit einem Tastendruckereignis tut, ist wahrscheinlich nicht verfügbar

Punkte, auf die @ angel_p_57 hinweisen muss

  1. Lösen Sie niemals Mutex von anderen Threads.
  2. Es gibt ein Missverständnis über die Verwendung von pthread_cond_ * (es ist NG, es nur zu verwenden, um auf ein solches Ereignis zu warten!)

Basierend auf diesen Punkten, was ich überhaupt machen wollte.

Bei der Implementierung der Nachrichtenverarbeitung oder ähnlichem Wenn Sie die Nachrichten in der Warteschlange kontinuierlich verarbeiten möchten, nachdem Sie sie in die Warteschlange gestellt haben (kurz: asynchrone Verarbeitung, z. B. Senden an die NW-Seite).

Ich möchte den Thread an einem bestimmten Punkt anhalten, da dies eine Verschwendung von Ressourcen ist, die sich verschwenderisch wiederholen, wenn keine Nachricht vorhanden ist. Kurz gesagt, ich möchte auf die Veranstaltung warten.

Vergleichen Sie, worauf Sie hingewiesen haben, mit dem, was Sie tun möchten

Hinweis: Die Verwendung von pthread_cond_wait in Code, der etwas mit einem Tastendruckereignis tut, ist wahrscheinlich nicht möglich Was ich tun möchte: Ich möchte auf ein Ereignis warten.

Aus.

~~ Ein Memo zum Anhalten mit Mutex in einem solchen Fall. ~~

~~ ** 2017/04/17 Ich habe es mit der richtigen Implementierungsmethode entsprechend der genannten Angelegenheit geschrieben. (Siehe unten im Artikel) ** ~~ ** 21.04.2017 erneut korrigiert **

Entschlüsselung voller Fehler, die ich am Anfang geschrieben habe

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <stdarg.h>
#include<stdint.h>
#include<assert.h>

//Legen Sie eine Schnur auf die Konsole
int consoleWrite(const char *fmt, ...)
{
    va_list list;
    va_start(list, fmt);
    int writed = vprintf(fmt, list);
    fflush(stdout);
    va_end(list);
    return writed;
}

//Akzeptieren Sie Zeichenfolgen von der Tastatur
size_t input(char *buf, size_t bufLen)
{
#define GabageBufSize 0x100
    uint8_t bin[GabageBufSize];
    char *savePtr = NULL;
    char *token = NULL;
    static_assert(sizeof(bin) == GabageBufSize, "Gabage buffer size not 255");

    fgets(buf, bufLen, stdin);
    token = strchr(buf, '\n');
    if (token != NULL)
    {
        *token = '\0';
    }
    else
    {
        buf[bufLen - 1] = '\0';
        while (token == NULL)
        {
            fgets(bin, GabageBufSize, stdin);
            token = strchr(bin, '\n');
            if (token != NULL)
            {
                break;
            }
        }
    }
    return strlen(buf);
}

//Dies ist eine schlechte Implementierung
void suspend(pthread_mutex_t* lock)
{
    pthread_mutex_trylock(lock);
//Wenn es noch nie gesperrt wurde, wird es hier gesperrt
    pthread_mutex_lock(lock);
    pthread_mutex_unlock(lock);
}

void *messageSender(void *lock)
{
    int count = 1;
    while (true)
    {
        consoleWrite(".");
        sleep(1);
        if ((count % 3) == 0)
        {
            //Warten Sie hier, bis das Ereignis eintritt.
            suspend((pthread_mutex_t*)lock);
        }
        count++;
    }
}

int main(int argc, char *argv[])
{
    pthread_t tid;
    pthread_mutex_t lock;
    char buf[32];
    pthread_mutex_init(&lock, NULL);
    pthread_create(&tid, NULL, messageSender, &lock);
    while (true)
    {
        input(buf, 32);
        pthread_mutex_unlock(&lock); //Der Entsperrvorgang wird von anderen Threads nicht garantiert.
        consoleWrite("unlocked.\n");
    }
    pthread_join(tid, NULL);
}

~~ Wenn Daten in die Warteschlange kommen, verwenden Sie den Rückruf und drücken Sie pthread_mutex_unlock ~~ Durch das Entsperren des ~~ Mutex-Objekts wird der Thread neu gestartet. ~~ ~~ In der obigen Demo wird der Teil, in dem die Daten in der Warteschlange gespeichert sind, durch die Eingabe über die Tastatur ersetzt. ~~

~~ Ich habe es implementiert, solange ich es konnte, ohne über Leistung nachzudenken, also ~~ ~~ Wenn Sie weitere gute Ideen haben, tun Sie dies bitte. ~~ Ich werde zu einem späteren Zeitpunkt ein Beispiel mit pthread_cond_wait in einem anderen Beitrag schreiben.


Noch mehr falsche Implementierung von hier

Referenz: Abschnitt: Manpage C Bibliotheksfunktionen (3) PTHREAD_COND

  1. pthread_cond_wait verwendet cond (= Bedingung: Bedingungsvariable) und Mutex als Argumente
  2. Das an pthread_cond_wait übergebene Mutex-Objekt muss gesperrt sein
  3. Von pthread_cond_wait gestoppte Threads werden von pthread_cond_signal neu gestartet
//Nur Korrekturunterschied

typedef struct Suspend
{
    pthread_mutex_t lockMutex;
    pthread_cond_t lockCond;
} Suspend;

void suspend(Suspend *lock)
{
//Falsche Verwendung
    pthread_mutex_trylock(&lock->lockMutex);
    pthread_cond_wait(&lock->lockCond,&lock->lockMutex);
    pthread_mutex_unlock(&lock->lockMutex);
}

void SuspendInit(Suspend *lock)
{
    pthread_cond_init(&lock->lockCond, NULL);
    pthread_mutex_init(&lock->lockMutex, NULL);
}

int main(int argc, char *argv[])
{
    pthread_t tid;
    Suspend lock;
    char buf[32];

    SuspendInit(&lock);
    pthread_create(&tid, NULL, messageSender, &lock);
    while (true)
    {
        input(buf, 32);
        pthread_cond_signal(&lock.lockCond);
        consoleWrite("unlocked.\n");
    }
    pthread_join(tid, NULL);
}

~~ Zunächst einmal habe ich das Gefühl, die Punkte, auf die hingewiesen wurde, behoben zu haben. ~~

Ich habe das Gefühl, dass ich es reparieren konnte ← Es lag an meinem Verstand. Neu implementiert mit Pipe (umbenannt von Suspend-Material in EventInfo-Material)

typedef struct EventInfo
{
    int state;
    int read;
    int write;
    pthread_mutex_t mutex;
} EventInfo;

#define EventInfo_WAIT_BUSY 0
#define EventInfo_WAIT_READY 1

//Warten Sie, bis das Ereignis eintritt
void EventInfoWait(EventInfo *lock)
{
    uint8_t msg;
    pthread_mutex_lock(&lock->mutex);
    lock->state = EventInfo_WAIT_READY;
    pthread_mutex_unlock(&lock->mutex);
    int r = read(lock->read, &msg, sizeof(uint8_t));
}

//nichts tun
void EventInfoRaisingEvent_None(EventInfo *lock)
{
}
//Nur benachrichtigen.
void EventInfoRaisingEvent_Send(EventInfo *lock)
{
    static uint8_t msg = 0xdeadbeef;
    write(lock->write, &msg, sizeof(uint8_t));
}
//Ereignis auslösen
void EventInfoRaisingEvent(EventInfo *lock)
{
    static void (*EventInfoWakeupSendMessage[2])(EventInfo * lock) =
        {
            EventInfoWakeupSendMessage_None,
            EventInfoWakeupSendMessage_Send};
    pthread_mutex_lock(&lock->mutex);
    EventInfoWakeupSendMessage[lock->state](lock);
    lock->state = EventInfo_WAIT_BUSY;
    pthread_mutex_unlock(&lock->mutex);
}

void *messageSender(void *lock)
{
    int count = 1;
    while (true)
    {
        consoleWrite(".");
        sleep(1);
        if ((count % 3) == 0)
        {
            //Warten Sie hier, bis das Ereignis eintritt.
            EventInfoWait((EventInfo *)lock);
        }
        count++;
    }
}

int EventInfoInit(EventInfo *lock)
{
    int pfd[2];
    int r = pipe(pfd);
    if (r != 0)
    {
        return -1;
    }
    lock->state = EventInfo_WAIT_BUSY;
    fcntl(pfd[1], F_SETFL, O_NONBLOCK);
    lock->read = pfd[0];
    lock->write = pfd[1];
    pthread_mutex_init(&lock->mutex, NULL);
    return 0;
}

int main(int argc, char *argv[])
{
    pthread_t tid;
    EventInfo lock;
    char buf[32];

    EventInfoInit(&lock);
    pthread_create(&tid, NULL, messageSender, &lock);
    while (true)
    {
        input(buf, 32);
        EventInfoRaisingEvent(&lock);
        consoleWrite("unlocked.\n");
    }
    pthread_join(tid, NULL);
    return 0;
}

Fix, vielleicht sollte dies in Ordnung sein, da es den ursprünglichen Zweck erreichen wird.

Recommended Posts

Thread unter Linux anhalten (korrigierte Version am Ende des Artikels)
Stellen Sie die neueste Version von Python in Linux (Debian) von Chromebook
Installieren Sie die neueste Version von Git auf Ihrem Linux-Server
Die Geschichte des Ausführens der asp.net Core 3.1-App auf der arm64-Version von Amazon Linux 2
[2020Juli] Überprüfen Sie die UDID des iPad unter Linux
Verwenden Sie die neueste Version von PyCharm unter Ubuntu
Zum Zeitpunkt des Python-Updates mit Ubuntu
Installieren Sie die neueste Version von CMake unter Ubuntu 18.04.4 LTS
Öffnen Sie die Chrome-Version von LINE über die Befehlszeile [Linux].
Überprüfen Sie den Linux-Verteilungstyp und die Version
Ankündigung der Verfügbarkeit von Java 11 LTS unter Amazon Linux 2
Hinweis zur Version von CUDA, cuDNN, in der Tensorflow-GPU funktioniert hat
Befehle und Dateien zum Überprüfen der Version von CentOS Linux
Rufen Sie den Hostnamen des Host-PCs mit Docker unter Linux ab
Richten Sie die Version von chromedriver_binary aus
Installieren Sie JDK unter Linux
Fügen Sie den Link unter Linux ein
[Neueste Version] Lassen Sie den Bot in regelmäßigen Abständen mit discord.py sprechen
Unter Linux ist der Zeitstempel einer Datei etwas vorbei.
So aktualisieren Sie die Python-Version von Cloud Shell in GCP
Testen Sie die Version des Argparse-Moduls
Abschluss des Docker-Befehls unter Linux
pyenv-change die Python-Version von virtualenv
Installieren Sie die neueste Version von Apache httpd 2.4 von der Quelle unter Cent OS 8
[Java] [Linux] Untersuchen, wie die Implementierung von untergeordneten Java-Prozessen unter Linux realisiert wird
Ich habe versucht, die Wartezeit der Ausführungswarteschlange eines Prozesses unter Linux zu messen
Version 2019: Trendanalyse für nicht autorisierten Zugriff (Beispiel eines Allzweckservers in der Cloud)
Folding @ Home unter Linux Mint soll zur Analyse des neuen Corona-Virus beitragen
Fassen Sie den Titel von Hottentori in Hateb zusammen und schauen Sie sich die Gegenwart des Web an