操作系统是Debian。
根据我的问题:
我编写了一个内核模块来通过修改系统调用表来拦截重新启动系统调用。
基本上只是通过以下方式保存旧的函数指针:
old_reboot = (void *) *(sys_call_table + __NR_reboot);
然后使其sys_call_table
可写并执行以下操作:
*(sys_call_table + __NR_reboot) = (unsigned long) my_reboot;
然后切换sys_call_table
回只读。我的重启系统调用如下所示:
asmlinkage long my_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg)
{
printk(KERN_INFO "Intercepted sys_reboot\n");
return old_reboot(magic1, magic2, cmd, arg);
}
然后我通过在 bash 中执行“reboot”命令来测试我的代码。
但是,我没有看到自定义重新启动功能记录到 dmesg / syslog,但我确实在加载或卸载模块时看到记录,因此至少该部分正在工作。
所以然后我尝试了完全相同的事情,只是使用open
系统调用而不是reboot
系统调用,并且它工作得很好。所以我能够拦截打开的系统调用,获取调用它的进程的 pid,将信息记录到 dmesg / syslog 等。
为什么我能够通过此方法拦截打开系统调用,但不能拦截重新启动系统调用?
重新启动实际上会调用重新启动系统调用吗?或者我在这里做错了什么?
编辑:
编写了一个小程序来直接调用重新启动系统调用并且它可以工作。 (我可以通过内核模块拦截重新启动系统调用)
重新启动_测试.c:
#include <unistd.h>
#include <sys/reboot.h>
int main()
{
sync();
reboot(RB_AUTOBOOT);
return 0;
}
但是,当我尝试使用重新启动命令重新启动时,我没有看到记录的拦截的重新启动系统调用。
作为附加测试,执行以下操作:
strace -f reboot
不显示重新启动系统调用,但使用我的小 C 程序,strace 确实显示重新启动系统调用。 (作为重启前的最后一行)
为什么 systemd 不使用重新启动系统调用?
如何配置我的系统以便所有重新启动都使用重新启动系统调用?
答案1
我确信这不是一个完整的答案。在检查 systemd 源代码时,似乎当需要紧急重新启动时(可能是由于“reboot -f”命令??),会直接系统调用与reboot(2)相同的入口点,但是绕过 glibc,以添加 glibc 库不支持的第五个参数。当调用传统的重新启动时,这似乎会调用 /usr/lib/systemd/systemd-shutdown ,它至少会在重新启动之前同步、卸载文件系统。它出现进行重新启动系统调用,但逻辑相当复杂。