语境:有时我的笔记本电脑不会进入睡眠模式并出现错误
Freezing of tasks failed after 20.008 seconds (0 tasks refusing to freeze, wq_busy=1)
我知道这表明工作队列行为不当(https://askubuntu.com/questions/692700/what-does-wq-busy-1-indicate-in-a-failure-to-suspend)经过多次摆弄,我最终检查了 magic 't' SysRq 的输出,这表明与 memstick 相关的工作队列显然已停止。的输出cat /proc/WORKER-PID/stack
总是被困在一个名为 的函数中memstick_set_rw_addr
。 IIUC 这个函数来自一个名为 memstick 的内核模块。另一个名为 的模块需要此模块rtsx_pci_ms
,然后我尝试卸载该模块。我这样做了modprobe -r rtsx_pci_ms
,但它什么也没显示,也不会返回(而且一旦 modprobe 运行,我什至无法杀死它,它根本就没有对killall -KILL modprobe
Control+C 做出反应)。 [然后我不得不关闭电源,所以我现在无法测试任何东西,但这种情况大约每周发生一两次,所以我会再次遇到它。]
所以现在问题如果“modprobe -r”卡住了,我如何强制杀死模块正在执行的任何操作?
答案1
如果不想杀死内核代码,则无法强制杀死它。内核代码不能在任意时间被杀死,因为它可能正在访问外围设备,它可能持有锁,它可能分配了一些需要释放的资源......用户态代码可以被杀死,因为内核持有所有这些资源代表进程,并在进程终止时清理它们。但在内核内部,每段代码都必须处理自己的清理工作。
通常,内核代码将检查信号,并在收到信号时干净地退出正在执行的操作。但是您遇到了内核错误。在这种情况下,你就不走运了。如果代码被卡住了,它就被卡住了。由于卡住的代码是在进程的系统调用上下文中执行的,因此该系统调用永远不会返回(除非内核内部的情况以某种方式自行纠正)。该进程正处于系统调用过程中,因此无法被终止。 KILL 信号会排队,如果系统调用返回,则进程将立即终止,但如果系统调用未返回,则进程将被卡住。