ReacOS源代码阅读之进程间通信--SetEvent

本文详细解析了ReacOS操作系统中SetEvent函数的实现原理及其内部调用流程,涉及NtSetEvent和KeSetEvent等核心函数,展示了事件对象如何在不同线程间传递信号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        ReacOS的源代码是从svn服务器下载,下载地址为:"svn://svn.reactos.org/reactos/trunk/reactos"(不包括双引号)。

        源代码的根目录存放在ReactOS。SetEvent的函数路径为 ReactOS\dll\win32\kernel32\client\synch.c 。这个函数的作用是设置事件为有信号状态,使得其他线程可以获取该事件。

/*
 * @implemented
 */
BOOL
WINAPI
DECLSPEC_HOTPATCH
SetEvent(IN HANDLE hEvent)
{
    NTSTATUS Status;

    /* Set the event */
    Status = NtSetEvent(hEvent, NULL);
    if (NT_SUCCESS(Status)) return TRUE;

    /* If we got here, then we failed */
    BaseSetLastNTError(Status);
    return FALSE;
}
        SetEvent函数调用NtSetEvent函数,该函数路径为 ReactOS\ntoskrnl\ex\event.c 。

/*
 * @implemented
 */
NTSTATUS
NTAPI
NtSetEvent(IN HANDLE EventHandle,
           OUT PLONG PreviousState  OPTIONAL)
{
    PKEVENT Event;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status;
    PAGED_CODE();
    DPRINT("NtSetEvent(EventHandle 0%p PreviousState 0%p)\n",
           EventHandle, PreviousState);

    /* Check if we were called from user-mode */
    if ((PreviousState) && (PreviousMode != KernelMode))
    {
        /* Entry SEH Block */
        _SEH2_TRY
        {
            /* Make sure the state pointer is valid */
            ProbeForWriteLong(PreviousState);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }

    /* Open the Object */
    Status = ObReferenceObjectByHandle(EventHandle,
                                       EVENT_MODIFY_STATE,
                                       ExEventObjectType,
                                       PreviousMode,
                                       (PVOID*)&Event,
                                       NULL);
    if (NT_SUCCESS(Status))
    {
        /* Set the Event */
        LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
        ObDereferenceObject(Event);

        /* Check if caller wants the old state back */
        if (PreviousState)
        {
            /* Entry SEH Block for return */
            _SEH2_TRY
            {
                /* Return previous state */
                *PreviousState = Prev;
            }
            _SEH2_EXCEPT(ExSystemExceptionFilter())
            {
                Status = _SEH2_GetExceptionCode();
            }
            _SEH2_END;
        }
    }

    /* Return Status */
    return Status;
}

        NtSetEvent函数较多代码都是SEH异常处理机制。主体部分首先是调用ObReferenceObjectByHandle获取KEVENT内核事件对象,然后调用KeSetEvent,该函数路径为ReactOS\ntoskrnl\ke\eventobj.c。关键部分源代码原本都已经有注释,这里就不画蛇添足了。

/*
 * @implemented
 */
LONG
NTAPI
KeSetEvent(IN PKEVENT Event,
           IN KPRIORITY Increment,
           IN BOOLEAN Wait)
{
    KIRQL OldIrql;
    LONG PreviousState;
    PKTHREAD Thread;
    ASSERT_EVENT(Event);
    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);

    /*
     * Check if this is an signaled notification event without an upcoming wait.
     * In this case, we can immediately return TRUE, without locking.
     */
    if ((Event->Header.Type == EventNotificationObject) &&
        (Event->Header.SignalState == 1) &&
        !(Wait))
    {
        /* Return the signal state (TRUE/Signalled) */
        return TRUE;
    }

    /* Lock the Dispathcer Database */
    OldIrql = KiAcquireDispatcherLock();

    /* Save the Previous State */
    PreviousState = Event->Header.SignalState;

    /* Set the Event to Signaled */
    Event->Header.SignalState = 1;

    /* Check if the event just became signaled now, and it has waiters */
    if (!(PreviousState) && !(IsListEmpty(&Event->Header.WaitListHead)))
    {
        /* Check the type of event */
        if (Event->Header.Type == EventNotificationObject)
        {
            /* Unwait the thread */
            KxUnwaitThread(&Event->Header, Increment);
        }
        else
        {
            /* Otherwise unwait the thread and unsignal the event */
            KxUnwaitThreadForEvent(Event, Increment);
        }
    }

    /* Check what wait state was requested */
    if (!Wait)
    {
        /* Wait not requested, release Dispatcher Database and return */
        KiReleaseDispatcherLock(OldIrql);
    }
    else
    {
        /* Return Locked and with a Wait */
        Thread = KeGetCurrentThread();
        Thread->WaitNext = TRUE;
        Thread->WaitIrql = OldIrql;
    }

    /* Return the previous State */
    return PreviousState;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值