2017-09-14 3 views
-1

Dies ist etwas verwandt mit einem former question von mir darüber, wie SleepEx tatsächlich funktioniert. The docs sagen, dass der Thread ausgeführt wird SleepEx wird fortgesetzt, wenn APC in die Warteschlange gestellt und APC möglicherweise in der Warteschlange, während der Thread APC bereits ausgeführt wird.Wie viele APCs werden während SleepEx verarbeitet?

Also, wie lange dauert der Thread weiterhin APCs? Ist es, bis die Warteschlange leer ist, wenn überprüft und in diesem Moment SleepEx die Kontrolle an den Anrufer zurückgibt? Oder wird nur genau ein APC von diesem Thread ausgeführt, dann kehrt SleepEx zurück und eine andere Ausführung von APC würde SleepEx benötigen, um noch einmal aufgerufen zu werden?

Ich habe das Gefühl, dass APCs ausgeführt werden, bis die Warteschlange zum ersten Mal leer ist. Vielen Dank!

+1

Es ist unerkennbar. Der Thread, der QueueUserApc() aufruft, hat keine Ahnung, ob der alertable Thread wieder aufgenommen wurde. Ob der alarmierbare Thread die Warteschlange vor der Wiederaufnahme abarbeitet oder nicht, spielt keine Rolle mehr. –

+0

@HansPassant Meine Frage ist nicht aus der Perspektive von QueueUserApc, aber wie SleepEx funktioniert. –

+0

@HansPassant - du irrst dich. Dies ist wahrscheinlich undokumentiert, aber genau bekannt - wenn die Thread-Rückkehr von der * APC * - Systemprüfung erfolgt, werden zusätzliche APC in den Thread eingefügt. und wenn ja - führe es aus. also wird das in loop sein, bis kein APC mehr in Thread – RbMm

Antwort

2

APCs werden ausgeführt, bis die Warteschlange leer ist. Wenn Ihr Code von APC zurückgegeben wird - Systemcheck sind andere APCs eingefügt - wenn ja - nächste APC wird ausgeführt, bis keine APC in Thread eingefügt. danach SleepEx (oder jede andere Warnbare Warte api) Rückkehr Kontrolle Sie


der APC in der nächsten Art und Weise ausgeführt - beim Aufruf bestimmter api (SleepEx, MsgWaitForMultipleObjectsEx, WaitForSingleObjectEx, WaitForMultipleObjectsEx .. mit der bAlertable Parameter-Set-Funktion zu TRUE) Kernel Check sind APC in Thread-Objekt eingefügt. Wenn ja - kernel den Benutzermodus-Threadkontext in den Stapel kopieren, dann den Threadkontext ändern (Benutzermodus-Antwortadresse auf ntdll.KiUserApcDispatcher gesetzt) ​​und zurückgeben. als Ergebnis-Code nicht von Ort aus, wo er in den Kernel eingeben (im Fall SleepEx ist dies ZwDelayExecution, die intern aufgerufen), sondern auf die KiUserApcDispatcher. Diese API führen APC und rufen Sie dann ZwContinue. Diese API deklariert als:

NTSYSAPI NTSTATUS NTAPI ZwContinue(PCONTEXT Context, BOOLEAN TestAlert); 

in Context Stelle verwendet in Stapel Thread-Kontext gespeichert, für die Rückkehr zu dem Punkt, von dem aus Warnbare api genannt wurde, und gibt an, ob TestAlert zusätzliche apc eingefügt überprüfen soll. Wenn Anruf ZwContinue mit TestAlert == FALSE System wird nicht mehr nach APC in Thread Queue suchen, bis Sie selbst nicht SleepEx oder andere bestimmte API aufrufen - so wird genau 1 APC ausgeführt werden. aber in KiUserApcDispatcherTestAlert hartcodiert zu TRUE - man kann einfach aussehen dies selbst, wenn Assembler-Code verstehen (die KiUserApcDispatcher ist winzig)

+0

Das ist absolut richtig, aber ich denke, Hans hat auch Recht: Wenn Ihr Code * von diesem Verhalten abhängt, tun Sie sehr wahrscheinlich etwas falsch. (Es kann Kantenfälle geben.) –

+0

@HarryJohnston - ja, stimme zu. aber ich bin einfach formale antwort zu fragen wie es ist. erklären, wie apc funktioniert – RbMm

Verwandte Themen