前两天看到老同学的一篇文章,感觉有点手痒,分析一下他的代码...
image
Reference: 内核模块打印进程线程PID信息
Repo:https://gitee.com/badbadguys/print_pid_driver/tree/master
需求是通过传入的PID,打印父进程的PID以及所有线程的PID,这里可以分为2步进行处理:
- 把PID传入内核模块,印象中是可以直接把echo PID到设备文件,输出到dmesg
- 拿到进程PID后,获取父进程/所有线程PID,打印
由于已经不会写驱动了,所以这里跳过第一步。。
获取一个进程的pid,ppid,以及子线程的pid
正常情况下我们ps一下就可以看到线程的pid和ppid
$ ps -ef | grep code
这里选择vscode,因为有很多子线程,输出比较乱,不过我们还是可以拿到一个合适的结果
UID PID PPID C STIME TTY TIME CMD
qiao 27407 1638 0 8月29 ? 00:00:17 /usr/share/code/code --no-sandbox --unity-launch
然后查看进程27407的子进程pid
$ ps -T -p 27407
PID SPID TTY TIME CMD
27407 27407 ? 00:00:08 code
27407 27419 ? 00:00:00 sandbox_ipc_thr
27407 27425 ? 00:00:00 ThreadPoolServi
27407 27427 ? 00:00:01 Chrome_IOThread
27407 27430 ? 00:00:00 gmain
27407 27431 ? 00:00:00 gdbus
27407 27433 ? 00:00:00 code
27407 27434 ? 00:00:02 code
27407 27435 ? 00:00:02 code
27407 27436 ? 00:00:02 code
27407 27437 ? 00:00:00 code
27407 27438 ? 00:00:00 Bluez D-Bus thr
27407 27439 ? 00:00:00 CrShutdownDetec
27407 27440 ? 00:00:00 dconf worker
27407 27444 ? 00:00:00 inotify_reader
27407 27449 ? 00:00:00 CompositorTileW
27407 27450 ? 00:00:00 VideoCaptureThr
27407 27451 ? 00:00:00 code
27407 27452 ? 00:00:00 ThreadPoolSingl
27407 27454 ? 00:00:00 code
27407 27455 ? 00:00:00 code
27407 27456 ? 00:00:00 code
27407 27457 ? 00:00:00 code
27407 27462 ? 00:00:00 code
27407 27487 ? 00:00:00 CacheThread_Blo
27407 27494 ? 00:00:00 ThreadPoolSingl
27407 8911 ? 00:00:00 ThreadPoolForeg
所以,当我们传入 pid 27407 的时候,我们应该得到如上的结果
开始coding 开始看code
git clone https://gitee.com/badbadguys/print_pid_driver.git
获取并打印父进程pid,线程pid的函数
// print_pid_driver/driver_module/print_pid_02.c +73
static int print_pid_operation(int input_pid)
{
struct pid *current_pid = find_get_pid(input_pid);
struct task_struct *current_task = pid_task(current_pid, PIDTYPE_PID);
struct pid* parent = get_task_pid(current_task->parent, PIDTYPE_PID);
pr_info("parent pid: %d\n", pid_nr(parent));
struct task_struct *t = current_task;
while((t=next_thread(t)) != current_task) {
struct pid* pid = get_task_pid(t, PIDTYPE_PID);
pr_info("thread pid: %d\n", pid_nr(pid));
}
return 0;
}
这里的思路是:
- 从pid获得task_struct结构体,其中parent成员指向当前进程的父进程的task_struct,获取父进程的pid
- 遍历current的线程链表,获取所有线程task_struct结构提,获取子线程的pid
其中几个关键函数:
/*
* Lookup a PID in the hash table, and return with it's count elevated.
*/
extern struct pid *find_get_pid(int nr);
extern struct task_struct *pid_task(struct pid *pid, enum pid_type);
extern struct task_struct *get_task_pid(struct task_struct *task, enum pid_type type);
static inline pid_t pid_nr(struct pid *pid);
使用这些函数,就可以在task_struct, struct pid, 以及我们需要打印的pid之间自由转换
!Notice
看注释里面,当我们使用 find_get_pid时,会增加pid的count,所以我们用完以后,应该需要 put_pid(pid) 解除对pid的引用?
总的看下来是非常清晰的,但是感觉代码埋了一些坑,就这样吧,坐等同学更新代码;!
最后运行一下老哥的代码:
qiao@qiao-PC:~/print_pid_driver$ sudo insmod driver_module/print_pid_02.ko
qiao@qiao-PC:~/print_pid_driver$ sudo cl
clashy clear clear_console client_test/
qiao@qiao-PC:~/print_pid_driver$ sudo client_test/test 27407
argv1 is 27407
begin to print pid ...
qiao@qiao-PC:~/print_pid_driver$ dmesg
[24731.846866] Goodbye from print_pid
[24762.188818] print_pid initializes devcie...
[24798.401626] print_pid dev open
[24798.401636] len: 4, len of uint32_t 4
[24798.401637] print_pid recevied req_pid 27407
[24798.401639] parent pid: 1638
[24798.401641] thread pid: 27419
[24798.401642] thread pid: 27425
[24798.401643] thread pid: 27427
[24798.401644] thread pid: 27430
[24798.401644] thread pid: 27431
[24798.401646] thread pid: 27433
[24798.401647] thread pid: 27434
[24798.401648] thread pid: 27435
[24798.401648] thread pid: 27436
[24798.401649] thread pid: 27437
[24798.401650] thread pid: 27438
[24798.401650] thread pid: 27439
[24798.401652] thread pid: 27440
[24798.401653] thread pid: 27444
[24798.401654] thread pid: 27449
[24798.401655] thread pid: 27450
[24798.401656] thread pid: 27451
[24798.401657] thread pid: 27452
[24798.401657] thread pid: 27454
[24798.401658] thread pid: 27455
[24798.401659] thread pid: 27456
[24798.401660] thread pid: 27457
[24798.401660] thread pid: 27462
[24798.401661] thread pid: 27487
[24798.401662] thread pid: 27494
[24798.401663] thread pid: 8911
结果还是OK的,和前面PS的一毛一样