[linux kernel] struct pid && the way the kernel used to cast uint32_t pid to struct task_struct

发布时间 2024-01-12 11:29:52作者: A2023

摘抄内容引用自linux kernel document

description

pre
the initialization and the manage of the struct pid is use IDR.(implement by hash table->(why not array?->dynamic malloc struct pid))
what is IDR?

A common problem to solve is allocating identifiers (IDs); The IDR provides the ability to map an ID to a pointer, while the IDA provides only ID allocation, and as a result is much more memory-efficient.

the description in linux kernel document
what is struct pid?

   A struct pid is the kernel's internal notion of a process identifier.**It refers to individual tasks, process groups, and sessions. ** While there are processes attached to it the struct pid lives in a hashtable, so it and then the processes that it refers to can be foundquickly from the numeric pid value. The attached processes may be quickly accessed by following pointers from struct pid.

   Storing pid_t values in the kernel and referring to them later has a problem. The process originally with that pid may have exited and the pid allocator wrapped, and another process could have come along and been assigned that pid.

   Referring to user space processes by holding a reference to struct task_struct has a problem. When the user space process exits the now useless task_struct is still kept. A task_struct plus a stack consumes around 10K of low kernel memory. More precisely this is THREAD_SIZE + sizeof(struct task_struct). By comparison a struct pid is about 64 bytes.

   Holding a reference to struct pid solves both of these problems. It is small so holding a reference does not consume a lot of resources, and since a new struct pid is allocated when the numeric pid value is reused (when pids wrap around) we don't mistakenly refer to new processes.

kernel data structure

each field of the struct pid
struct pid
{
refcount_t count;
unsigned int level;
spinlock_t lock;
/* lists of tasks that use this pid /
struct hlist_head tasks[PIDTYPE_MAX];
struct hlist_head inodes;
/
wait queue for pidfd notifications */
wait_queue_head_t wait_pidfd;
struct rcu_head rcu;
struct upid numbers[];
};

//this enum is use to find the corresponding-type task referenced by the pid.
enum pid_type
{
PIDTYPE_PID,//index to individual tasks referenced by this pid
PIDTYPE_TGID,//index to thread group leader process
PIDTYPE_PGID,//index to grooup leader process
PIDTYPE_SID,//index to the session leader process
PIDTYPE_MAX,//the value indicate over-flow
};

the way kernel used to find struct task_struct by user-use uint_32 pid

pid(int)--->[IDR,hash]--->struct pid; ---->corresponding hlist_head:cantain only on node ---> hlist_entry(contain_of)----->struct task_struct;