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