0

私は、RHEL 5.x から RHEL 6.x (2.6.32 カーネル) に 4 つのプロプライエタリ (読み取り: 非 GPL) Linux カーネル ドライバー (私が書いていない) を移植している最中です。ドライバーはすべて、ユーザー空間の「セッション」を通知するために kill_proc() を使用しますが、この関数は最近のカーネル (2.6.18 から 2.6.32 の間のどこか) から削除されています。この質問がここや他の場所で何度も聞かれるのを見て、かなり広範囲に検索しましたが、多くの提案された解決策の中で、関数がエクスポートされなくなったか、GPL のみの関数が必要なために機能しません (以下を参照)。 . 独自のドライバーで機能するソリューションを知っている人はいますか?

指定: kill_proc(pid, sig, 1);

私が見つけた最も簡単な解決策は、 kill_proc_info(sig, SEND_SIG_PRIV, pid); を使用することでした。ただし、kill_proc_info はエクスポートされなくなったため、使用できません。

kill_pid_info() が提案されています (これは rcu_read_lock() を設定した後に kill_proc_info() によって呼び出されます)。 GPL 使用のみを目的としてエクスポートされており、これは独自のドライバーです. 構造体 pid* を取得する別の方法はありますか?

また、kill_pid_info() は、rcu_read_lock() をセットアップしてから、group_send_sig_info() を呼び出します。残念ながら、group_send_siginfo() はエクスポートされず、struct task_struct* も必要ですが、必要な find_task_by_vpid() 関数もエクスポートされません。

もう 1 つの提案は kill_pid() でしたが、これにも struct pid* が必要であり、関数 find_vpid() は GPL 用にのみエクスポートされています。

send_sig() と send_sig_info() の提案もありましたが、これらにも構造体 task_struct* が必要です。また、find_task_by_pid() はエクスポートされず、pid_task() は (GPLd) find_vpid() で構造体 pid* を取得する必要があります。 . また、これらの関数は rcu_read_lock() を設定せず、グループ フラグに FALSE 値も渡します (一方、kill_proc は TRUE 値を使用することになりました)。そのため、微妙な違いがいくつかある可能性があります。

それは私が見つけることができたすべてです。私の場合に役立つ提案はありますか?前もって感謝します。

4

1 に答える 1

3

私の質問に対する回答がなかったので、カーネル コードの多くを読んでいて、解決策を見つけたと思います。

kill_proc() と同じセマンティクスを提供する唯一のエクスポートされた関数は kill_pid() のようです。GPL の find_vpid() 関数を使用して必要な構造体 pid* を取得することはできませんが、構造体 task_struct* を取得できれば、そこから構造体 pid* を次のように取得できます: task->pids[PIDTYPE_PID].pid

find_task_by_vpid() はエクスポートされなくなったため、タスクを見つける唯一の方法は、タスク リスト全体を調べて探すことです。したがって、提案された解決策は次のとおりです。

int my_kill_proc(pid_t pid, int sig) {
    int error = -ESRCH;           /* default return value */
    struct task_struct* p;
    struct task_struct* t = NULL; 
    struct pid* pspid;
    rcu_read_lock();
    p = &init_task;               /* start at init */
    do {
        if (p->pid == pid) {      /* does the pid (not tgid) match? */
            t = p;    
            break;
        }
        p = next_task(p);         /* "this isn't the task you're looking for" */
    } while (p != &init_task);    /* stop when we get back to init */
    if (t != NULL) {
        pspid = t->pids[PIDTYPE_PID].pid;
        if (pspid != NULL) error = kill_pid(pspid,sig,1);
    }
    rcu_read_unlock();
    return error;
}

ハッシュ テーブルを使用するよりも、タスク リスト全体を検索する方がはるかに時間がかかることはわかっていますが、これですべてです。私が持っているいくつかの懸念/質問:

  1. これには rcu_read_lock() で十分ですか? 代わりに preempt_disable() のようなものを使用する方がよいでしょうか?
  2. 構造体 task_struct は、pids 配列に PIDTYPE_PID エントリを持たないことがありますか? もしそうなら、NULL をチェックするだけで十分ですか?
  3. 私はカーネルを使用するのが初めてです。これを改善するための他の提案はありますか?
于 2013-05-01T16:27:04.310 に答える