2012-01-14 13 views
2

カーネルモジュールからバックグラウンドを設定しようとしていますが、動かすことができません。カーネルモジュールからGNOMEバックグラウンドを変更する

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()を使用してメッセージを出力すると、正常に動作します。タイマーでスクリプトをスケジュールするのではなく、ブロックで繰り返し実行すると、完全に機能します。しかし、/ usr/bin/sudoではなく/ bin/trueを実行するとフリーズします。静的構造体を静的でないものに置き換えると、同じ問題が発生します。

私はカーネル呼び出しユーザ空間プログラムは、一般的に避けるべき持つGNOME 2とカーネル2.6.32.37

+5

なぜこれを行うにはカーネルモジュールを使用していますか? – Dave

+3

このようにしないでください。なぜなら、カーネルはデスクトップを実行しなくても実行できるからです。絶対に必要な場合は、デスクトップ起動スクリプトを変更してカーネルにモジュールについて問い合わせを行い、バックグラウンドを変更してください。 –

+0

@同僚のいたずらです。それが手の込んだものだとしましょう。 – Juan

答えて

4

を使用しています:このように、それが政策決定にカーネルコードを結び付け

  • さまざまなバイナリの場所とそれらが取るオプション。

  • システムの階層構造に違反しています。一般に、カーネルは、反対ではなくユーザ空間からの呼び出しを処理することになっています。

  • ユーザー空間が予期しない状態になると予期しない方法で破損する可能性があります。一般user-mode helper APIを通じて -

カーネルは、しかし、呼び出しユーザ空間のプログラムをサポートしています。これは一般に、電力管理などのユーザ空間協力を必要とする比較的低レベルの操作や、固有の制約のためにカーネル空間で合理的に実行できない操作に使用されます。それは非常にまれにしか使用されておらず、他のすべての選択肢が使い尽くされた後でなければなりません。

あなたはおそらく最初、これらの他の選択肢を検討する必要があります。

  • は、デーモンがNetlinkソケットを介して、あなたのモジュールに接続してもらいます。この方法は、ユーザ空間のプログラマのために広く使用されている(例えば、udev)。このアプローチを使用するプログラムの作成を容易にするユーザ空間ライブラリ(例えば、libnl)があります。

  • モジュールによって作成され、更新されたsysfsファイルをデーモンにポーリングしてもらってください。

  • デーモンに新しいデバイスノードを介してモジュールと通信させますか?

  • あなたのモジュールがCPUを点火して煙信号を送信するようにしてください - ちょうどをください。他の選択肢がない限り直接ユーザー空間プログラムを呼び出さないでください。

カーネルとユーザー空間通信の最も一般的な方法を説明しているhow-toがあります。

作業中のデスクトップを想定しているので、デーモンモニタを使用すると、カーネルモジュールを確実に実行できるはずです。サイドボーナスとして、コードの一部をユーザスペースに移動することができます。ここでは、デバッグ機能がはるかに広範囲で、開発のリスクと時間がかかりません。

EDIT:ところで

call_usermodehelper()は、プロセスコンテキストから呼び出されることになっています。タイマーから呼び出しても、その要件を満たしているわけではありません。コードは基本的に割り込みコンテキストで実行されます。

+0

+1、私の問題は解決しませんが、私は多くのことを理解するのを助けました –

関連する問題