【问题标题】:Semaphores values信号量值
【发布时间】:2010-04-05 16:32:42
【问题描述】:

我有一个关于使用信号量的问题

HANDLE WINAPI CreateSemaphore(...);

无论如何我可以获得信号量的当前值吗?

【问题讨论】:

    标签: multithreading winapi semaphore


    【解决方案1】:

    这里是使用 Native Api 的解决方案,由 http://undocumented.ntinternals.net/ 记录。 我省略了一些事情,因为这些会使代码更长。当您了解本机 api 的语法时,代码很简单。例如(几乎)所有本机 api 函数,这些由 ntdll 导出并且微软没有很好地记录,返回 NTSTATUS,并且不要使用类似的函数来获取 Set/GetLastError ()。如果 NtQuerySemaphore 失败(Status != STATUS_SUCCESS),您可能需要在此处查找错误代码:http://source.winehq.org/source/include/ntstatus.h

    好的,让我们进入代码,它非常简单,首先定义一些可以从 ntinernals.net 获得的结构。然后在ntdll.dll中获取NtQuerySemaphore的地址。您不需要使用 LoadLibrary,因为每个进程都加载了 ntdll.dll。

    NtQuerySemaphore 也很简单,第一个参数是信号量的句柄,第二个参数是您要检索的信息类(在我们的例子中 SemaphoreBasicInformation = 0x0)。 第三个参数是一个指向结构的指针,用于查看信息。第四个参数是结构的大小。第五个是 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);
    }
    

    最后一件事,请注意,微软可能会删除或更改此功能的工作方式。

    干杯恶魔

    【讨论】:

      【解决方案2】:

      不,这是故意的。即使您可以获得“当前”值,该值很可能在您对其进行任何操作之前已经发生了变化。使用它做任何事情的唯一方法是原子地获取和设置值 - 例如,等待信号量空闲在同样的操作。

      【讨论】:

      • 那会不会很麻烦?您需要进入临界区;等待信号量;操纵计数器;退出临界区; ?
      • @Yan Cheng CHEOK:按预期使用时,信号量的大多数使用并不麻烦,不是。进入临界区后,然后等待信号量是很不寻常的——相反,您通常只会使用这两个结构中的一个,而不是同时使用两者。
      【解决方案3】:
      【解决方案4】:

      您可以随时使用:

      //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()...
      

      希望对您有所帮助。

      【讨论】:

        【解决方案5】:

        我觉得你需要打电话

        DWORD WINAPI WaitForSingleObject
        

        第二个参数设置为 0(请求立即结果)。

        并根据结果采取行动。

        希望对你有帮助 杰罗姆·瓦格纳

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-24
          • 2021-02-02
          • 1970-01-01
          相关资源
          最近更新 更多