(1)
此函数根据用户层提供的进程号 nr 获取对应的进程描述符struct pid,并使进程描述符中的字段count的值加1,即此进程的用户数加1。
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);
(2)
将进程描述符 struct pid的count成员原子的+1。
static inline struct pid *get_pid(struct pid *pid)
{
if (pid)
atomic_inc(&pid->count);
return pid;
}
(3)
根据提供的局部进程号获取对应的进程描述符 struct pid :
参数nr是进程对应的局部进程号,一般与进程号相同。
参数ns是struct pid_namespace型变量,是对进程命名空间信息的描述。
struct pid *find_pid_ns(int nr, struct pid_namespace *ns)
{
struct upid *pnr;
hlist_for_each_entry_rcu(pnr,
&pid_hash[pid_hashfn(nr, ns)], pid_chain)
if (pnr->nr == nr && pnr->ns == ns)
return container_of(pnr, struct pid,
numbers[ns->level]);
return NULL;
}
EXPORT_SYMBOL_GPL(find_pid_ns);
// 参数nr是进程对应的局部进程号,一般与进程号相同。
struct pid *find_vpid(int nr)
{
return find_pid_ns(nr, task_active_pid_ns(current));
}
EXPORT_SYMBOL_GPL(find_vpid);
我执行top命令,top的pid为44284。
#include
#include
#include
static int __init find_get_pid_init(void)
{
struct pid * kpid = find_get_pid(44284); //top的进程号:44284
//struct pid * kpid=find_get_pid(current->pid); //根据进程号,调用函数获取进程描述符信息
printk("the count of struct pid is :%d\n", kpid->count);
printk("the level of struct pid is :%d\n", kpid->level);
printk("the upid of struct pid is :%d\n", kpid->numbers[kpid->level].nr);
return -1;
}
module_init(find_get_pid_init);
MODULE_LICENSE("GPL");
(1)struct task_struct
列举了struct task_struct的一些成员,接下来我将通过进程数值ID号,来获取struct task_struct,并打印这些成员。
struct task_struct {
......
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
atomic_t usage;
pid_t pid;
pid_t tgid;
/* process credentials */
char comm[TASK_COMM_LEN]; //不包括路径的可执行文件名称
......
}
其中成员 comm 使用 get_task_comm 访问(使用 task_lock() 锁定它),并 由 setup_new_exec 正常初始化
// linux-4.10.1/fs/exec.c
char *get_task_comm(char *buf, struct task_struct *tsk)
{
/* buf must be at least sizeof(tsk->comm) in size */
task_lock(tsk);
strncpy(buf, tsk->comm, sizeof(tsk->comm));
task_unlock(tsk);
return buf;
}
EXPORT_SYMBOL_GPL(get_task_comm);
(2)get_pid_task
get_pid_task函数通过 struct pid 和 type 来获取进程的struct task_struct结构体。内部实现主要通过pid_task(pid, type)函数来获取struct task_struct结构体。
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);
get_pid_task函数会将struct task_struct成员的usage变量加1。
备注:内核中函数带有get/put前缀的函数通常都会将引用计数+1或者-1。
#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
(3)pid_task
pid_task这个函数是内核中用来获取struct task_struct的常用的辅助函数。用来获取pid->tasks[type]哈希表中的第一个task_struct实例。
struct task_struct *pid_task(struct pid *pid, enum pid_type type)
{
struct task_struct *result = NULL;
if (pid) {
struct hlist_node *first;
first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]),
lockdep_tasklist_lock_is_held());
if (first)
result = hlist_entry(first, struct task_struct, pids[(type)].node);
}
return result;
}
EXPORT_SYMBOL(pid_task);
参数struct pid是内核对进程号的内部表示。
参数type是pid_type型变量,此变量是一个枚举型变量,定义如下:
enum pid_type
{
PIDTYPE_PID, //进程的进程号
PIDTYPE_PGID, //进程组领头进程的进程号
PIDTYPE_SID, //会话领头进程的进程号
PIDTYPE_MAX //表示进程号类型的数目 == 3
};
#include
#include
#include
#include
#include
/* Module parameter */
static int pid = 0;
module_param(pid, int, 0);
//内核模块初始化函数
static int __init lkm_init(void)
{
struct pid * kpid;
struct task_struct *task;
char task_name[TASK_COMM_LEN] = {0};
kpid = find_get_pid(pid);
task = get_pid_task(kpid, PIDTYPE_PID);
printk("task name = %s , task pid = %d\n", get_task_comm(task_name, task), task->pid);
return -1;
}
module_init(lkm_init);
MODULE_LICENSE("GPL");
[root@localhost get_task_by_pid]# insmod get_task_by_pid.ko pid=1
[root@localhost get_task_by_pid]# dmesg -c
[62943.164059] task name = systemd , task pid = 1