java程序如何实现监听的原理_程序语言下事件监听底层是如何实现的?

事件处理程序本质上是一种回调函数,回调函数的意思就是把调用的权限移交给了事件发起人,事件发起的时候由负责事件的程序自动进行调用。至于事件的来源,就得看从什么角度考虑了。

从进程的角度,少部分事件的确是通过轮询获取的,大部分则是通过消息循环结构。一个消息循环一般独占一个线程,大致上可以用伪代码写成:

while GetEvent

ProcessEvent

也就是获取一个事件然后处理这个事件的循环。处理事件通常就是调用事件处理程序。

那么如何获取事件?除了轮询以外,通常是借助操作系统的帮助。操作系统提供某些阻塞式的调用,例如select,epoll,Windows有GetMessage,WaiForMultipleObjects等。这些阻塞式调用一般可以处理多种信号源,在其中某一个发生变化时返回,从而同时追踪多种输入。

除了事件循环以外,另一种设计则是操作系统直接触发特定的回调函数,典型的例子包括Linux的signal,aio,Windows的SendMessageWithCallback等。这种回调通常也会立即中断当前正在进行的系统调用,这样可以将回调与事件循环相结合,在回调过程中设置标记,阻塞结束时检查标记,即可将这种回调融入通常的事件循环。

那么,从操作系统的角度来看呢?操作系统内核可以任意调度用户进程。在用户进程进行系统调用的时候,转入内核态,内核就将当前进程挂起起来;当相应事件发生的时候,内核再将对应用户进程唤醒,让它继续执行。可见,内核其实也是个事件回调系统。

一层一层说到底,内核的事件又从何而来呢?一个重要的机制称为中断,一句话解释,它就是硬件实现的信号处理程序。CPU通常都按顺序执行指令,内核会依次执行用户程序,在用户进程全部挂起的时候,会执行一个idle进程,里面死循环执行低功耗指令。一个重要的例外是中断,CPU有中断引脚,中断引脚上的电平变换,会立即让CPU进行中断过程:CPU中的硬件结构会立即进入内核态,读取中断向量表,然后根据其中的地址跳转到相应的代码进行执行。中断处理程序一般会首先保存现场,查询中断复用硬件上的信息,保存到特定的数据结构,复位中断,然后立即返回到内核态。内核接下来会查询中断信息并执行专用的处理程序,这些程序最终会使用户态程序恢复执行,然后再重复这个过程。可以看出,这其实就是用户态里的信号处理程序和事件循环的翻版。

除了硬件中断以外,还有一些中断是CPU内部触发的,比较重要的是时钟中断,处理流程是一样的。也有某些硬件使用时钟中断进行轮询,例如USB。

总结来说:硬件通过中断通知内核,内核通过阻塞调用和事件处理程序通知用户进程(线程),用户框架处理通知并触发事件处理程序。

再补充一点:可以看出,硬件中断的触发频率是有限度的,如果硬件很繁忙,会不会漏掉中断,那我键盘的输入会不会就丢了呢?答案是,中断只负责通知有新信息,而不是传输所有信息。硬件只在第一个新信息的时候通知,硬件自己有自己的缓冲区,消息会暂存在缓冲区里,如果缓冲区满则一般会丢弃新消息。CPU处理中断(一般对内核来说是硬件中断处理程序结束后,检查标记然后进行,称为软中断),通过总线将缓冲区里的数据读完,然后等待新中断。另一种方式是使用专用的硬件——DMA控制器,将缓冲区里的数据直接读取到内存里,然后由DMA控制器发出中断通知内核处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值