Linux kernel 如何在Linux内核中断后强制重新扫描?

Linux kernel 如何在Linux内核中断后强制重新扫描?,linux-kernel,task,switch-statement,interrupt,Linux Kernel,Task,Switch Statement,Interrupt,我在玩kretprobes,我面临一个问题。为了响应来自用户进程的某些事件(例如,特定的系统调用),我希望从该进程地址空间读取数据。因为在kretprobe条目处理程序中,我们处于中断上下文中,我不可能从这里获取用户页面(它可能处于休眠状态),所以我推迟了系统中的工作 为了确保用户进程在延迟的工作完成之前不会更改其内存,我将其放入TASK_INTERRUPTIBLE并使用set_tsk_need_resched()。我希望在iret期间,该标志将被测试,调度器将选择另一个任务。看起来它不是那样工

我在玩kretprobes,我面临一个问题。为了响应来自用户进程的某些事件(例如,特定的系统调用),我希望从该进程地址空间读取数据。因为在kretprobe条目处理程序中,我们处于中断上下文中,我不可能从这里获取用户页面(它可能处于休眠状态),所以我推迟了系统中的工作

为了确保用户进程在延迟的工作完成之前不会更改其内存,我将其放入TASK_INTERRUPTIBLE并使用set_tsk_need_resched()。我希望在iret期间,该标志将被测试,调度器将选择另一个任务。看起来它不是那样工作的,用户任务在中断后立即回到cpu上,在我有机会查看它之前更改了它的内存

是否有其他方法可以确保任务切换在iret之后立即发生


提前感谢

您的方法根本上是有缺陷的。中断本质上是异步的;即使您关闭了中断返回和延迟工作项之间的竞争,如果中断被延迟,您也可以得到相同的竞争。考虑:

  • 用户:设置X=1
  • 中断:安排工作
  • 用户:设置X=2
  • 工作队列:读取X
vs

  • 用户:设置X=1
  • 中断:(因硬件异常而延迟…)
  • 用户:设置X=2
  • 中断:安排工作
  • 工作队列:读取X
同样的结果,不是吗?所以不要尝试

更重要的是,即使在内核代码中也可能发生中断。如果应用程序处于不阻塞和修改内存的系统调用的中间,则必须在它阻止您完成之前完成该调用。强迫它进入可中断状态有可能导致死锁;内核代码可能持有自旋锁,或者不处于安全状态,无法进行调度

请注意,这正是中断处理程序无法睡眠的原因——当调用上下文可能不准备睡眠时,它们会强制调用上下文睡眠。这正是你想要做的

简言之,你所想的比赛无法解决;从根本上说,您的工作队列项只是将延迟添加到中断处理程序,而中断处理程序已经有一些不可预测的延迟量。因此,用户进程将始终有一个窗口,在该窗口中它可能会弄乱内存。此外,用户进程可能不处于可以安全中断的状态


因此,不用担心——只要确保用户进程不会破坏整个系统,并让用户进程自己确保不会破坏(即,告诉用户进程的开发人员,如果他想让硬件正常工作,就不要弄乱这个内存).

今天我发现这其实是一个很好的方法。我在运行进程时遇到的问题是因为我没有处于中断上下文中:kprobe经过优化(即x86上的jmp指令而不是int3),这导致我的代码在内核中的用户上下文中执行。如果kprobe_optimized()函数工作正常,这应该可以顺利处理,在这种情况下,我们可以在将任务设置为可中断后直接调用schedule(),而不是重新启动并让中断处理程序的序言检查标志
TIF_NEED_RESCHED
。实际上,
kprobe\u optimized()
在任何情况下如果是kretprobe,都会返回false,这是由于内部处理kretprobe的方式所致:它使用kprobe的聚合器,为聚合器正确设置了哪个优化标志,但不为列表中的kprobe设置。我通过导出函数
get\u kprobe()
并使用它检索kprobe聚合器的地址来解决这个问题,最终我能够从中正确检查它是否优化

我认为在内核中解决这个问题的最佳方法(性能方面)是将优化标志从聚合器复制到它列出的每个kprobe。这样,
kprobe\u optimized()
将返回正确的值。另一种方法是在
kprobe\u optimized()
中添加更多代码,以检查此kprobe是否是聚合器列表的一部分,并检查聚合器而不是实际的kprobe

无论如何,这很有趣

中断发生是因为我在那里放置了一个kprobe,所以我知道用户进程正在运行,并且被我的探测器中断,并且在调用中断处理程序时没有运行。从那以后,应该可以像页面错误处理程序那样轻松地将其置于睡眠状态,这样我就可以在以后继续工作并使其恢复运行。假设您映射了一个文件并尝试读取AS,但是当您尝试读取->页面错误->内核将使您处于可中断状态,直到数据从磁盘到达:这正是我在这里尝试实现的。谢谢你的回答