从内核模块更改gnome背景

时间:2012-01-14 01:56:46

标签: c linux module timer kernel

我正在尝试从内核模块设置背景,但我无法让它工作。

我已经得到的是:

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

1 个答案:

答案 0 :(得分:4)

通常应避免使用内核调用用户空间程序:

  • 它将内核代码与策略决策联系起来,例如各种二进制文件的位置及其选项。

  • 它违反了系统的分层结构。一般来说,内核应该服务于来自用户空间的调用,而不是相反的。

  • 如果用户空间处于无法预料的状态,它可能会以意想不到的方式中断。

内核确实支持调用用户空间程序 - 通常是通过user-mode helper API。这通常用于需要用户空间协作的相对低级别的操作,例如电源管理,或者用于由于其固有限制而无法在内核空间中合理执行的操作。也就是说,它很少使用,只有在所有其他替代方案都用尽之后才会使用。

您应该首先考虑这些其他选择:

  • 让守护程序通过Netlink套接字连接到您的模块。由于其对用户空间程序员的熟悉,该方法被广泛使用(例如udev)。有一些用户空间库(例如libnl)可以显着促进使用这种方法的程序的创建。

  • 对您的模块创建并更新的sysfs文件进行守护程序轮询。

  • 让守护程序通过新设备节点与您的模块通信。

  • 让您的模块通过点燃您的CPU发送烟雾信号 - 除非您没有其他选择,否则不要直接调用用户空间程序。

有一个how-to描述了最常用的内核/用户空间通信方法。

由于你假设一个工作桌面,有一个守护进程监视你的内核模块应该是可行的。作为一个额外的好处,您将能够将一些代码移动到用户空间,其中调试工具更加广泛,开发风险更低,耗时更长。

修改

顺便说一句,call_usermodehelper()应该从进程上下文中调用。从计时器调用它并不满足该要求 - 您的代码基本上在中断上下文中运行。