在我的kext的stop()函数中,我调用iflt_detach()来分离注册的iff过滤器。但是,似乎(无论出于何种原因),可以在stop()函数之外调用过滤器的detach()函数。在那种情况下,我应该在stop函数中做什么?我无法返回KERN_SUCCESS,因为这会导致KEXT被卸载,对延迟调用detach()函数有明显的副作用。
以下代码片段来自enetlognke.c并显示了stop()函数:
kern_return_t com_dts_apple_kext_enetlognke_stop(kmod_info_t * ki,void * d)
{
kern_return_t retval = KERN_FAILURE; //默认结果,除非我们知道我们是
//从界面分离。
if (gFilterRegistered == FALSE)
return KERN_SUCCESS;
if (gUnregisterProc_started == FALSE)
{
// only want to start the detach process once.
iflt_detach(gEnetFilter);
gUnregisterProc_started = TRUE;
}
if (gUnregisterProc_complete)
{
retval = KERN_SUCCESS;
}
else
{
el_printf("enetlognke_stop: incomplete\n");
}
if (retval == KERN_SUCCESS)
{
// Free KEXT resources
}
return retval;
}
gUnregisterProc_complete从此模块的dispatch()函数中设置为TRUE。因此,如果该函数调用被延迟(并且gUnregisterProc_complete为FALSE),则stop函数将通过返回KERN_FAILURE来否决卸载。
所以,我的问题是:
如果返回KERN_FAILURE,内核会再次调用KEXT的stop()函数吗?如果没有,是什么触发了重试KEXT卸载和调用stop()函数?
KERN_FAILURE要返回的正确代码是否过滤器尚未分离?
答案 0 :(得分:0)
据推测,一旦没有线程继续运行你的回调,detach
函数在这种情况下会在另一个线程上调用吗?
如果是这样,这将成为一个相当简单的线程同步问题。设置一个标志变量,例如has_detached
并通过递归互斥锁保护它。
在停止功能中:在调用iflt_detach()
之前锁定互斥锁。如果返回,则标志尚未设置,在挂起互斥锁时暂停标志的地址,直到标志置位。最后,解锁,并从停止功能返回。
在分离功能的最后:锁定互斥锁,设置标志,向可能正在休眠的线程发送唤醒并解锁。如果解锁调用处于尾部位置,则在执行分离函数的代码和卸载所述代码之间没有竞争条件。
实际上,这将阻止卸载kext,直到您的过滤器完全分离为止。
注意:我没有尝试过这种网络过滤器的特殊情况(我还没有编写过滤器kext),但它通常是我在其他文件夹中使用过的模式
注2:我说使用递归锁来防止死锁,以防你在iflt_detach()
内部的同一线程上调用detach函数。