传入PID参数打印父进程PID以及所有线程PID

前两天看到老同学的一篇文章,感觉有点手痒,分析一下他的代码...

image

Reference: 内核模块打印进程线程PID信息
Repo:https://gitee.com/badbadguys/print_pid_driver/tree/master

需求是通过传入的PID,打印父进程的PID以及所有线程的PID,这里可以分为2步进行处理:

    1. 把PID传入内核模块,印象中是可以直接把echo PID到设备文件,输出到dmesg
    1. 拿到进程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;
}

这里的思路是:

  1. 从pid获得task_struct结构体,其中parent成员指向当前进程的父进程的task_struct,获取父进程的pid
  2. 遍历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的一毛一样

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。