Семафоры значения - PullRequest
       6

Семафоры значения

2 голосов
/ 05 апреля 2010

У меня вопрос по поводу использования семафоров

HANDLE WINAPI CreateSemaphore(...);

Могу ли я узнать текущее значение семафора?

Ответы [ 5 ]

7 голосов
/ 06 апреля 2010

Здесь решение с использованием Native Api, документированное http://undocumented.ntinternals.net/. Я пропустил несколько вещей, потому что они сделали бы код еще длиннее. Код прост, когда вы понимаете синтаксис нативного API. Например, (почти) все нативные функции API, они экспортированы ntdll и плохо документированы Microsoft, возвращают NTSTATUS и не используют функцию simliar для получения Set / GetLastError (). Если сбой NtQuerySemaphore (Status! = STATUS_SUCCESS), вы можете посмотреть код ошибки здесь: http://source.winehq.org/source/include/ntstatus.h.

Хорошо, давайте перейдем к коду, он довольно прост, сначала определив некоторые структуры, которые вы можете получить с ntinernals.net. Затем получить адрес NtQuerySemaphore в ntdll.dll. Вам не нужно использовать LoadLibrary, потому что каждый процесс загружен ntdll.dll.

NtQuerySemaphore также прост, первый параметр - дескриптор семафора, второй - класс информации, который вы хотите получить (в нашем случае SemaphoreBasicInformation = 0x0). Третий параметр - указатель на структуру, которая восстанавливает информацию. Четвертый paramwter - это размер структуры. В-пятых, будет ReturnLength, например, если вы можете получить имя семафора с помощью этой функции, этот параметр может содержать необходимый размер буфера после первого вызова с неверным SemaphoreInformationLength.

Довольно! Код:)

#include <windows.h>
#include <stdio.h>

typedef LONG NTSTATUS;

typedef NTSTATUS (NTAPI *_NtQuerySemaphore)(
    HANDLE SemaphoreHandle, 
    DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */
    PVOID SemaphoreInformation,      /* but this is to much to dump here     */
    ULONG SemaphoreInformationLength, 
    PULONG ReturnLength OPTIONAL
); 

typedef struct _SEMAPHORE_BASIC_INFORMATION {   
    ULONG CurrentCount; 
    ULONG MaximumCount;
} SEMAPHORE_BASIC_INFORMATION;


int main (int argc, char *argv[])
{
    _NtQuerySemaphore NtQuerySemaphore;
    HANDLE Semaphore;
    SEMAPHORE_BASIC_INFORMATION BasicInfo;
    NTSTATUS Status;


    Semaphore = CreateSemaphore (NULL, 50, 100, "Test");

    NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress (GetModuleHandle ("ntdll.dll"), "NtQuerySemaphore");

    if (NtQuerySemaphore)
    {

        Status = NtQuerySemaphore (Semaphore, 0 /*SemaphoreBasicInformation*/, 
            &BasicInfo, sizeof (SEMAPHORE_BASIC_INFORMATION), NULL);

        if (Status == ERROR_SUCCESS)
        {       
            printf ("CurrentCount: %lu", BasicInfo.CurrentCount);
        }
    }

    CloseHandle (Semaphore);
}

Еще одна вещь, предупреждаем, Microsoft может удалить или изменить способ работы этой функции.

Приветствия злой пирог

5 голосов
/ 05 апреля 2010

Нет, и это намеренно. Даже если бы вы могли получить «текущее» значение, это значение вполне могло бы измениться, прежде чем вы могли бы что-либо с ним сделать. Единственный способ сделать что-либо с ним - это получить и установить значение атомарно - например, дождаться освобождения семафора и установить его в «принадлежащий» (этому коду) работа.

1 голос
/ 05 апреля 2010
0 голосов
/ 23 февраля 2012

Вы всегда можете использовать:

//ReleaseSemaphore(Last Parameter- Previous Count)

Если вы хотите, чтобы ваш основной поток дождался завершения всех потоков.

//CreateEvent
//Assign threads
//ResetEvent
//WaitForSingleObject( hEvent, INFINITE) ;

//When you call the threads function and after releasing Semaphore.
//Check for the previousCount, if it is equal to MAX_SEMAPHORES-1, SetEvent()...

Надеюсь, это поможет.

0 голосов
/ 05 апреля 2010

Я думаю, вам нужно позвонить

DWORD WINAPI WaitForSingleObject

со вторым аргументом, установленным в 0 (запрошен немедленный результат).

и выполняйте действия в зависимости от результата.

Надеюсь, это поможет вам, Джером Вагнер

...