Im Laufe des Kommentars zu einer kürzlich gestellten Frage ergab sich eine Nebenfrage, worüber Zeigen Sie eine Löschungsanforderung für einen Pthreads-Thread mit der Abbruchfähigkeit PTHREAD_CANCEL_DEFERRED
an, von der erwartet werden kann, dass sie bearbeitet wird. Verweise auf den Standard und ein bisschen Lawyering folgten. Mir geht es nicht besonders darum, ob ich mich in meinen Kommentaren zu dieser Frage geirrt habe, aber ich möchte sichergehen, dass ich die Bestimmungen von POSIX richtig verstehe.
Der relevanteste Abschnitt des Standards sagt
Wenn ein Thread die Löschbarkeit aktiviert hat und eine Löschanforderung mit diesem Thread als Ziel erfolgt ist und der Thread dann eine Funktion aufruft, die ein Löschpunkt [...] ist, muss die Löschanforderung vor der Ausführung des Threads bearbeitet werden Funktion kehrt zurück. Wenn ein Thread die Löschbarkeit aktiviert hat und eine Löschanforderung mit dem Thread als Ziel erfolgt, während der Thread an einem Löschpunkt angehalten ist, wird der Thread geweckt und die Löschanforderung muss bearbeitet werden.
Was bedeutet es jedoch, dass ein Thread "suspendiert" wird? POSIX definiert explizit den Begriff für Prozesse, aber nicht, soweit ich es feststellen kann, für Threads. Auf der anderen Seite dokumentiert POSIX die Thread-Suspendierung als eines der Verhaltensweisen einer Handvoll von Funktionen, einschließlich, aber nicht beschränkt auf einige von denen, die sich auf Synchronisationsobjekte beziehen. Sollte man dann zu dem Schluss kommen, dass diese kollektiv als relevante Definition des Begriffs dienen?
Und das alles bezieht sich auf die Frage, die zu dieser Frage geführt hat, da POSIX die Thread-Sperre nicht als Teil des Verhaltens von read()
, fread()
oder einer der allgemeinen Dateien oder Streams I / O Funktionen, wenn ein Thread aufgrund einer E / A-Blockierung keine Fortschritte macht, bedeutet dies, dass er für die Zwecke der Stornierung "ausgesetzt" wird?
Ein unterbrochener Thread ist einer, der, wie Sie sagen, bei einem Socket-Lesevorgang blockiert ist und darauf wartet, dass ein Semaphor verfügbar wird usw.
Da POSIX-Implementierungen an den kniffligen Kanten variieren und die Möglichkeit besteht, dass ein Thread in einer Funktion blockiert wird, die kein Abbruchpunkt ist, kann es sein, dass er sich auf die Löschung in Code stützt, der portiert werden soll sei mehr Ärger als es wert ist.
Ich habe es nie benutzt, ich habe immer Code gewählt, um explizit einen Thread zum Beenden anzuweisen (normalerweise eine Nachricht in einer Pipe oder Warteschlange). Dies ist sehr einfach mit einem kommunizierenden Sequential Processes oder Actor Model System.
Auf diese Weise kann die Säuberung unter eigener Kontrolle erfolgen, um Speicher usw. freizusetzen. Ich habe keine Ahnung, ob ein abgebrochener Thread seinen Speicher aufräumt (ich vermute nicht), oder ob es die Option für eine at_exit () - Art gibt (die es möglicherweise gibt). Im Großen und Ganzen denke ich, dass das Anwendungsverhalten gründlicher kontrolliert wird, wenn es nur einen einzigen Weg gibt, den ein Thread beenden kann.
== EDIT ==
@JohnBollinger,
Die verwendete Sprache If a thread has cancelability enabled and a cancellation request is made with the thread as a target while the thread is suspended at a cancellation point
könnte als IF a thread has cancelability enabled AND IF cancelled and IF implementation suspends blocked threads AND IF the thread is blocked THEN the thread shall be awakened...
interpretiert werden. Mit anderen Worten, sie überlassen es dem Implementierer des POSIX-Subsystems.
Cygwins Implementierung von select () führt nicht (oder zumindest nicht) dazu, dass der Thread ausgesetzt wird. Stattdessen erzeugt es einen Abfragethread pro Dateideskriptor, um auf signalisierbare Aktivität zu testen, aufgrund des grundsätzlichen Fehlens von irgendetwas wie select () in Windows (es kommt näher, aber keine Zigarre. Win32 select () funktioniert nur auf Sockets). Implementierungen von select () in den 1980er Jahren haben oft auch so funktioniert.
Aus Gründen wie diesen mag es POSIX nicht klar zu definieren, wann ein Thread suspendiert wird. Historisch gesehen waren viele Implementierungen von select () wie diese, was es zu einem Minenfeld für ein Standardkomitee machte, um zu sagen, wann ein Thread suspendiert werden konnte oder nicht. Natürlich würden die durch select () verursachten Komplexitäten auch auf einen Prozess zutreffen, aber da POSIX einen suspendierten Prozess definiert, erscheint es seltsam, dass die Definition nicht auf Threads erweitert werden konnte.
Vielleicht liegt es daran, wie Threads implementiert werden; Es ist denkbar, dass Sie eine POSIX-Implementierung haben, die keine OS-Threads verwendet (ein bisschen wie die frühen Implementierungen von ADA in den Tagen, als Betriebssysteme überhaupt keine Threads ausgeführt haben), und in einer solchen Implementierung ist ein blockierter Thread möglicherweise nicht gesperrt (im Sinne von keine CPU-Zyklen zu nehmen).
Definition von suspend im Kontext von Threads:
3.107 Bedingungsvariable
Ein Synchronisationsobjekt, mit dem ein Thread die Ausführung wiederholt anhalten kann, bis ein zugehöriges Prädikat wahr wird. Ein Thread, dessen Ausführung an einer Bedingungsvariablen ausgesetzt ist, wird für die Bedingungsvariable blockiert.
Von: Ссылка
Das ist keine direkte Antwort, nur eine Definition - zu groß für einen Kommentar. Gesperrt == ausgesetzt.
read, fread und friends sind Systemaufrufe und als solche werden sie einen Kontextwechsel ausführen und aus dem Kernelkontext ausführen, bis diese Funktionen abgeschlossen sind. Das Unterbrechen eines Kernel-Kontexts liegt außerhalb des Geltungsbereichs von Pthreads und führt daher nicht zu einer Stornierung.
Ich habe keine Referenz dafür, aber soweit ich weiß, hat die Thread-Suspendierung im Zusammenhang mit Posix-Threads etwas mit dem Synchronisationsobjekt zu tun (wie Futex's).
Tags und Links c language-lawyer posix