GNU/Linux >> Belajar Linux >  >> Linux

Cara efisien untuk menemukan task_struct dengan pid

Ada cara yang lebih baik untuk mendapatkan instance dari task_struct dari modul. Selalu mencoba untuk menggunakan fungsi pembungkus/rutin pembantu karena mereka dirancang sedemikian rupa jika programmer driver melewatkan sesuatu, kernel dapat mengurusnya sendiri. Misalnya - penanganan kesalahan, pemeriksaan kondisi, dll.

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

taskp = get_pid_task(pid, PIDTYPE_PID);

dan untuk mendapatkan PID tipe pid_t. Anda perlu menggunakan API di bawah -

find_get_pid(pid_no);

Anda tidak perlu menggunakan "rcu_read_lock() " dan "rcu_read_unlock() " saat memanggil API ini karena "get_pid_task() " secara internal memanggil rcu_read_lock(),rcu_read_unlock() sebelum memanggil "pid_task() " dan menangani konkurensi dengan benar. Itu sebabnya saya katakan di atas selalu gunakan pembungkus semacam ini.

Cuplikan fungsi get_pid_task() dan find_get_pid() di bawah ini :-

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);

Dalam modul kernel, Anda juga dapat menggunakan fungsi pembungkus dengan cara berikut -

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

PS:untuk informasi lebih lanjut tentang API, Anda dapat melihat kernel/pid.c


Jika Anda ingin menemukan task_struct dari sebuah modul, find_task_by_vpid(pid_t nr) dll. tidak akan berfungsi karena fungsi ini tidak diekspor.

Dalam sebuah modul, Anda dapat menggunakan fungsi berikut sebagai gantinya:

pid_task(find_vpid(pid), PIDTYPE_PID);

Tidak ada yang menyebutkan bahwa pid_task() fungsi dan penunjuk (yang Anda peroleh darinya) harus digunakan di dalam bagian kritis RCU (karena menggunakan struktur data yang dilindungi RCU). Jika tidak mungkin ada BUG setelah bebas digunakan .
Ada banyak kasus penggunaan pid_task() di sumber kernel Linux (mis. di posix_timer_event() ).
Misalnya:

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!) */

Cari tahu lebih lanjut tentang RCU API dari Kernel.org

P.S. Anda juga bisa menggunakan fungsi API khusus seperti find_task_by_pid_ns() dan find_task_by_vpid() di bawah rcu_read_lock() .

Yang pertama adalah untuk mencari melalui namespace tertentu:

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

Yang kedua adalah untuk mencari melalui namespace dari current tugas.


Apa salahnya menggunakan salah satu dari berikut ini?

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. temukan dan hapus file dengan ruang menggunakan perintah find di Linux

  2. Cara paling efisien untuk menyalin file di Linux

  3. Cara menemukan file .pid untuk proses tertentu

  1. Grep Rekursif Vs Temukan / -type F -exec Grep {}; Mana yang Lebih Efisien/Lebih Cepat?

  2. Cara Andal Untuk Menjebloskan Proses Anak Menggunakan `nsenter:`?

  3. Cara Mengetahui Apakah Sistem Mendukung Intel Amt?

  1. Bagaimana cara menemukan ID proses di Ubuntu?

  2. Apakah ada cara untuk memeriksa apakah ada tautan simbolik yang mengarah ke direktori?

  3. Contoh desain server jaringan yang efisien, ditulis dalam C