我正在尝试从内核模块设置背景,但我无法让它工作。
我已经得到的是:
static void change_desktop(unsigned long unused);
static struct timer_list timer = TIMER_INITIALIZER(change_desktop, 0, 0);
static int umh_test( void ) {
char *argv[] = { "/usr/bin/sudo", "-u", "mmarquez", "/bin/bash", "/home/mmarquez/script.sh", NULL };
static char *envp[] = {
"HOME=/home/mmarquez",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
NULL
};
call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC);
return call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC);
}
static void change_desktop(unsigned long unused) {
umh_test()
timer.expires = jiffies + 10 * HZ;
add_timer(&timer);
}
int __init init_module(void) {
change_desktop(0);
return 0;
}
void __exit exit_module(void) {
}
脚本是:
#!/bin/bash
nautilus_pid=$(pgrep -u $LOGNAME -n nautilus)
eval $(tr '\0' '\n' < /proc/$nautilus_pid/environ | grep '^DBUS_SESSION_BUS_ADDRESS=')
export DBUS_SESSION_BUS_ADDRESS
cp /home/mmarquez/Pictures/logo.png /home/mmarquez/Pictures/bg.png
gconftool-2 --set /desktop/gnome/background/picture_filename --type string /home/mmarquez/Pictures/bg.png
问题是计算机在几秒钟后冻结。
如果不是运行脚本而是使用printk()打印消息,它运行良好。如果我不使用计时器安排脚本,而是在块中重复运行它,它可以完美地工作。但是如果我运行/ bin / true而不是/ usr / bin / sudo,它也会冻结。用非静态替换静态结构会留下同样的问题。
我正在使用gnome 2和内核2.6.32.37
答案 0 :(得分:4)
通常应避免使用内核调用用户空间程序:
它将内核代码与策略决策联系起来,例如各种二进制文件的位置及其选项。
它违反了系统的分层结构。一般来说,内核应该服务于来自用户空间的调用,而不是相反的。
如果用户空间处于无法预料的状态,它可能会以意想不到的方式中断。
内核确实支持调用用户空间程序 - 通常是通过user-mode helper API。这通常用于需要用户空间协作的相对低级别的操作,例如电源管理,或者用于由于其固有限制而无法在内核空间中合理执行的操作。也就是说,它很少使用,只有在所有其他替代方案都用尽之后才会使用。
您应该首先考虑这些其他选择:
让守护程序通过Netlink套接字连接到您的模块。由于其对用户空间程序员的熟悉,该方法被广泛使用(例如udev)。有一些用户空间库(例如libnl)可以显着促进使用这种方法的程序的创建。
对您的模块创建并更新的sysfs文件进行守护程序轮询。
让守护程序通过新设备节点与您的模块通信。
让您的模块通过点燃您的CPU发送烟雾信号 - 除非您没有其他选择,否则请不要直接调用用户空间程序。
有一个how-to描述了最常用的内核/用户空间通信方法。
由于你假设一个工作桌面,有一个守护进程监视你的内核模块应该是可行的。作为一个额外的好处,您将能够将一些代码移动到用户空间,其中调试工具更加广泛,开发风险更低,耗时更长。
修改强>
顺便说一句,call_usermodehelper()
应该从进程上下文中调用。从计时器调用它并不满足该要求 - 您的代码基本上在中断上下文中运行。