如何使用C从PID获取进程名称
How to get process name from PID using C
我想从 task_struct
获取进程名称,但是
我收到一个错误取消引用指向不完整类型的指针 (task->comm)。
我必须使用 pid_task
函数。
我不知道为什么它不起作用。
ssize_t simple_read(struct file *filp, char __user *user_buf, size_t count, loff_t *f_pos) {
int len=0;
pid_struct = find_get_pid(pid);
task = pid_task(pid_struct,PIDTYPE_PID);
len = sprintf(user_buf,"\nname %s\n ",task->comm);
return len;
}
要找到进程的 task_struct,我们可以使用 kernel/pid.c 中定义的函数 pid_task。
struct task_struct *pid_task(struct pid *pid, enum pid_type type)
参数:
pid : Pointer to the struct pid of the process.
pid_type: PIDTYPE_PID,
PIDTYPE_PGID,
PIDTYPE_SID,
PIDTYPE_MAX
如果我们有进程的 pid,要找到 pid 结构,我们可以使用 functionfind_get_pid,它也在 kernel/pid.c
中定义
struct pid *find_get_pid(pid_t nr)
在下面的模块中,我们创建了一个名为 task_by_pid 的 read/write proc 条目。我们想要找到使用其 pid 的 task_struct 的任何进程,我们可以将数字写入 proc 条目。
当我们读取proc表项时,会显示我们写入的pid对应的进程名。
proc_task_pid:
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/proc_fs.h>
#include <linux/pid.h>
#include <linux/pid_namespace.h>
int p_id;
struct pid *pid_struct;
struct task_struct *task;
static struct proc_dir_entry *proc_write_entry;
char *proc_name="task_by_pid";
int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
pid_struct = find_get_pid(p_id);
task = pid_task(pid_struct,PIDTYPE_PID);
len = sprintf(buf,"\nname %s\n ",task->comm);
return len;
}
int write_proc(struct file *file,const char *buf,int count,void *data )
{
int ret;
char *id;
id = (char *)kmalloc(1000*sizeof(char),GFP_KERNEL);
printk(KERN_INFO "buf passed %s",buf);
if(copy_from_user(id,buf,count))
return -EFAULT;
printk(KERN_INFO "id passed %s",id);
p_id = simple_strtoul(id,NULL,0);
printk(KERN_INFO "pid %d ret %d",p_id,ret);
return sizeof(buf);
}
void create_new_proc_entry()
{
proc_write_entry = create_proc_entry(proc_name,0666,NULL);
if(!proc_write_entry)
{
printk(KERN_INFO "Error creating proc entry");
return -ENOMEM;
}
proc_write_entry->read_proc = read_proc ;
proc_write_entry->write_proc = write_proc;
printk(KERN_INFO "proc initialized");
}
int proc_init (void) {
create_new_proc_entry();
return 0;
}
void proc_cleanup(void) {
printk(KERN_INFO " Inside cleanup_module\n");
remove_proc_entry(proc_name,NULL);
}
MODULE_LICENSE("GPL");
module_init(proc_init);
module_exit(proc_cleanup);
使用下面的make文件编译:
ifneq ($(KERNELRELEASE),)
obj-m := proc_task_pid.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
Compile it using
$make
插入内核:
$ insmod proc_task_pid.ko
现在让我们尝试找到 pid 为“1”的进程的名称,它始终是 init。
$ printf "1" > /proc/task_by_pid
$ cat /proc/task_by_pid
name init
正如预期的那样,输出是 "init"。因此,我们可以使用其 pid 找到任何进程的 task_struct。
来自 here 的源代码。
我想从 task_struct
获取进程名称,但是
我收到一个错误取消引用指向不完整类型的指针 (task->comm)。
我必须使用 pid_task
函数。
我不知道为什么它不起作用。
ssize_t simple_read(struct file *filp, char __user *user_buf, size_t count, loff_t *f_pos) {
int len=0;
pid_struct = find_get_pid(pid);
task = pid_task(pid_struct,PIDTYPE_PID);
len = sprintf(user_buf,"\nname %s\n ",task->comm);
return len;
}
要找到进程的 task_struct,我们可以使用 kernel/pid.c 中定义的函数 pid_task。
struct task_struct *pid_task(struct pid *pid, enum pid_type type)
参数:
pid : Pointer to the struct pid of the process.
pid_type: PIDTYPE_PID,
PIDTYPE_PGID,
PIDTYPE_SID,
PIDTYPE_MAX
如果我们有进程的 pid,要找到 pid 结构,我们可以使用 functionfind_get_pid,它也在 kernel/pid.c
中定义struct pid *find_get_pid(pid_t nr)
在下面的模块中,我们创建了一个名为 task_by_pid 的 read/write proc 条目。我们想要找到使用其 pid 的 task_struct 的任何进程,我们可以将数字写入 proc 条目。
当我们读取proc表项时,会显示我们写入的pid对应的进程名。
proc_task_pid:
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/proc_fs.h>
#include <linux/pid.h>
#include <linux/pid_namespace.h>
int p_id;
struct pid *pid_struct;
struct task_struct *task;
static struct proc_dir_entry *proc_write_entry;
char *proc_name="task_by_pid";
int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
pid_struct = find_get_pid(p_id);
task = pid_task(pid_struct,PIDTYPE_PID);
len = sprintf(buf,"\nname %s\n ",task->comm);
return len;
}
int write_proc(struct file *file,const char *buf,int count,void *data )
{
int ret;
char *id;
id = (char *)kmalloc(1000*sizeof(char),GFP_KERNEL);
printk(KERN_INFO "buf passed %s",buf);
if(copy_from_user(id,buf,count))
return -EFAULT;
printk(KERN_INFO "id passed %s",id);
p_id = simple_strtoul(id,NULL,0);
printk(KERN_INFO "pid %d ret %d",p_id,ret);
return sizeof(buf);
}
void create_new_proc_entry()
{
proc_write_entry = create_proc_entry(proc_name,0666,NULL);
if(!proc_write_entry)
{
printk(KERN_INFO "Error creating proc entry");
return -ENOMEM;
}
proc_write_entry->read_proc = read_proc ;
proc_write_entry->write_proc = write_proc;
printk(KERN_INFO "proc initialized");
}
int proc_init (void) {
create_new_proc_entry();
return 0;
}
void proc_cleanup(void) {
printk(KERN_INFO " Inside cleanup_module\n");
remove_proc_entry(proc_name,NULL);
}
MODULE_LICENSE("GPL");
module_init(proc_init);
module_exit(proc_cleanup);
使用下面的make文件编译:
ifneq ($(KERNELRELEASE),)
obj-m := proc_task_pid.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
Compile it using
$make
插入内核:
$ insmod proc_task_pid.ko
现在让我们尝试找到 pid 为“1”的进程的名称,它始终是 init。
$ printf "1" > /proc/task_by_pid
$ cat /proc/task_by_pid
name init
正如预期的那样,输出是 "init"。因此,我们可以使用其 pid 找到任何进程的 task_struct。
来自 here 的源代码。