如何直接"分配"使用Windows API进入信号量的过程?

时间:2017-01-29 00:32:35

标签: c++ windows process

我使用Microsoft的以下代码作为模板:

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

#define MAX_SEM_COUNT 10
#define THREADCOUNT 12

HANDLE ghSemaphore;

DWORD WINAPI ThreadProc( LPVOID );

int main( void )
{
    HANDLE aThread[THREADCOUNT];
    DWORD ThreadID;
    int i;

    // Create a semaphore with initial and max counts of MAX_SEM_COUNT

    ghSemaphore = CreateSemaphore( 
        NULL,           // default security attributes
        MAX_SEM_COUNT,  // initial count
        MAX_SEM_COUNT,  // maximum count
        NULL);          // unnamed semaphore

    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }

    // Create worker threads

    for( i=0; i < THREADCOUNT; i++ )
    {
        aThread[i] = CreateThread( 
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) ThreadProc, 
                     NULL,       // no thread function arguments
                     0,          // default creation flags
                     &ThreadID); // receive thread identifier

        if( aThread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return 1;
        }
    }

    // Wait for all threads to terminate

    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

    // Close thread and semaphore handles

    for( i=0; i < THREADCOUNT; i++ )
        CloseHandle(aThread[i]);

    CloseHandle(ghSemaphore);

    return 0;
}

DWORD WINAPI ThreadProc( LPVOID lpParam )
{

    // lpParam not used in this example
    UNREFERENCED_PARAMETER(lpParam);

    DWORD dwWaitResult; 
    BOOL bContinue=TRUE;

    while(bContinue)
    {
        // Try to enter the semaphore gate.

        dwWaitResult = WaitForSingleObject( 
            ghSemaphore,   // handle to semaphore
            0L);           // zero-second time-out interval

        switch (dwWaitResult) 
        { 
            // The semaphore object was signaled.
            case WAIT_OBJECT_0: 
                // TODO: Perform task
                printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
                bContinue=FALSE;            

                // Simulate thread spending time on task
                Sleep(5);

                // Release the semaphore when task is finished

                if (!ReleaseSemaphore( 
                        ghSemaphore,  // handle to semaphore
                        1,            // increase count by one
                        NULL) )       // not interested in previous count
                {
                    printf("ReleaseSemaphore error: %d\n", GetLastError());
                }
                break; 

            // The semaphore was nonsignaled, so a time-out occurred.
            case WAIT_TIMEOUT: 
                printf("Thread %d: wait timed out\n", GetCurrentThreadId());
                break; 
        }
    }
    return TRUE;
}

我想调整它,而不是确定信号量填充方式的线程,而是由进程完成,这意味着如果有进程运行和/或任何进程,信号量将填充他们的habdles没有关闭,事实上我通过使用这个新函数更改线程函数的工作来完成它。

DWORD WINAPI ThreadProc( LPVOID lpParam )
{

    // lpParam not used in this example
    UNREFERENCED_PARAMETER(lpParam);

    DWORD dwWaitResult; 
    BOOL bContinue=TRUE;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    memset(&si,0,sizeof(si));
    si.cb=sizeof(si);

    while(bContinue)
    {
        // Try to enter the semaphore gate.

        dwWaitResult = WaitForSingleObject( 
            ghSemaphore,   // handle to semaphore
            0L);           // zero-second time-out interval

        CreateProcess("arbol.exe",NULL,NULL,NULL,0,0,NULL,NULL,&si,&pi);    
        WaitForSingleObject(pi.hProcess,INFINITE);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

        switch (dwWaitResult) 
        { 
            // The semaphore object was signaled.
            case WAIT_OBJECT_0: 
                // TODO: Perform task
                printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
                bContinue=FALSE;            

                // Simulate thread spending time on task
                Sleep(5);

                // Release the semaphore when task is finished

                if (!ReleaseSemaphore( 
                        ghSemaphore,  // handle to semaphore
                        1,            // increase count by one
                        NULL) )       // not interested in previous count
                {
                    printf("ReleaseSemaphore error: %d\n", GetLastError());
                }
                break; 

            // The semaphore was nonsignaled, so a time-out occurred.
            case WAIT_TIMEOUT: 
                printf("Thread %d: wait timed out\n", GetCurrentThreadId());
                break; 
        }
    }
    return TRUE;
}

有了这个,虽然决定信号量填充的是线程,但在实际意义上,它是由完成执行和关闭过程句柄决定的。

但这看起来是解决这个问题的一种蹩脚方式,我敢打赌,如果需要从这些流程中获得额外的东西,这样做可能会在将来产生问题。

如何创建信号量,那么真正决定信号量填充的是进程?为了澄清,这将是一种可能的解决方案,我认为无论如何都不可能。

让我们考虑您可以通过以下方式创建流程:

 aThread[i] = CreateProcess( 
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) ThreadProc, 
                     NULL,       // no thread function arguments
                     0,          // default creation flags
                     &ThreadID); // receive thread identifier

然后LPTHREAD_START_ROUTINE在工作方面与工艺相当。

信号量应该支持Windows API中的Interprocess Synchronization,但我找不到任何专门使用进程的示例,而且我也不知道如何才能完成。

关于如何实现我想要的任何想法?

问候。

1 个答案:

答案 0 :(得分:1)

你想要一个命名的信号量。每个进程通过使用相同名称创建信号量来共享信号量。

创建一个命名信号量。与之前相同,但最后一个参数获取传递给它的字符串:

HANDLE hSemaphore = CreateSemaphore(NULL, 
                                    MAX_SEM_COUNT,
                                    MAX_SEM_COUNT,
                                    L"TheSemaphoreForMyApp");

子进程在启动时可以附加到同一个信号量,并使用OpenSemaphore获取句柄。

HANDLE hSemaphore = OpenSemaphore(EVENT_ALL_ACCESS, 
                                  FALSE,
                                  L"TheSemaphoreForMyApp");

您不必将字符串硬编码为信号量名称。父进程每次都可以创建唯一的名称,然后将该名称(例如命令行参数)传递给子进程。这将允许您的程序的多个实例与子进程合作。