GNU/Linux >> Linux の 問題 >  >> Linux

pid で task_struct を見つける効率的な方法

モジュールから task_struct のインスタンスを取得するためのより良い方法があります。ドライバー プログラマーが何かを見逃した場合、カーネルが独自に対処できるように設計されているため、常にラッパー関数/ヘルパー ルーチンを使用するようにしてください。例 - エラー処理、条件チェックなど

/* Use below API and you will get a pointer of (struct task_struct *) */

taskp = get_pid_task(pid, PIDTYPE_PID);

pid_t 型の PID を取得します。以下の API を使用する必要があります -

find_get_pid(pid_no);

rcu_read_lock()」を使用する必要はありません " および "rcu_read_unlock() " get_pid_task() のため、これらの API の呼び出し中に " " "pid_task()" を呼び出す前に、内部的に rcu_read_lock(),rcu_read_unlock() を呼び出します "そして並行性を適切に処理します。そのため、私は常にこの種のラッパーを使用すると言ったのです.

以下の get_pid_task() および find_get_pid() 関数のスニペット:-

struct task_struct *get_pid_task(struct pid *pid, enum pid_type type)
{
    struct task_struct *result;
    rcu_read_lock();
    result = pid_task(pid, type);
    if (result)
        get_task_struct(result);
    rcu_read_unlock();
    return result;
}
EXPORT_SYMBOL_GPL(get_pid_task);

struct pid *find_get_pid(pid_t nr)
{
    struct pid *pid;

    rcu_read_lock();
    pid = get_pid(find_vpid(nr));
    rcu_read_unlock();

    return pid;
}
EXPORT_SYMBOL_GPL(find_get_pid);

カーネルモジュールでは、次の方法でもラッパー関数を使用できます-

taskp = get_pid_task(find_get_pid(PID),PIDTYPE_PID);

PS:API の詳細については、kernel/pid.c を参照してください


task_struct を見つけたい場合 モジュールから、find_task_by_vpid(pid_t nr) これらの関数はエクスポートされていないため、機能しません。

モジュールでは、代わりに次の関数を使用できます:

pid_task(find_vpid(pid), PIDTYPE_PID);

pid_task() 関数とポインタ (そこから取得したもの) RCU クリティカル セクション内で使用する必要があります (RCU で保護されたデータ構造を使用しているため)。 それ以外 use-after-free BUG が存在する可能性があります .
pid_task() を使うケースが多い Linux カーネル ソース (例:posix_timer_event()) )。
例:

rcu_read_lock();
/* search through the global namespace */
task = pid_task(find_pid_ns(pid_num, &init_pid_ns), PIDTYPE_PID);
if (task)
    printk(KERN_INFO "1. pid: %d, state: %#lx\n",
           pid_num, task->state); /* valid task dereference */
rcu_read_unlock(); /* after it returns - task pointer becomes invalid! */

if (task)
    printk(KERN_INFO "2. pid: %d, state: %#lx\n",
           pid_num, task->state); /* may be successful,
                                   * but is buggy (task dereference is INVALID!) */

Kernel.org で RCU API の詳細を確認してください

追記find_task_by_pid_ns() のような特別な API 関数を使用することもできます そして find_task_by_vpid() rcu_read_lock() の下 .

最初のものは、特定の名前空間を検索するためのものです:

task = find_task_by_pid_ns(pid_num, &init_pid_ns); /* e.g. init namespace */

2 つ目は、current の名前空間を検索するためのものです。


次のいずれかを使用することの何が問題になっていますか?

extern struct task_struct *find_task_by_vpid(pid_t nr);
extern struct task_struct *find_task_by_pid_ns(pid_t nr,
            struct pid_namespace *ns);

Linux
  1. ディレクトリを指すシンボリック リンクがあるかどうかを確認する方法はありますか?

  2. シェルで最後に実行されたコマンドの実行時間を見つける方法はありますか?

  3. Linux で find コマンドを使用して、スペースのあるファイルを検索して削除する

  1. Linux でファイルをコピーする最も効率的な方法

  2. 大量のファイルをすばやく削除する方法

  3. 1 つのディレクトリにある多数のファイルを移動する最も効率的な方法は何ですか?

  1. Recursive Grep Vs Find / -type F -exec Grep {};どちらがより効率的/高速ですか?

  2. `nsenter:`を使用して子プロセスを投獄する信頼できる方法?

  3. 特定のプロセスの .pid ファイルを見つける方法