Chapter 2: Process Management and Scheduling
thetasks[type]list.hlist_add_head_rcuis a standard function to traverse a list that additionally
ensures as per the RCU mechanism (see Chapter 5) that the iteration is safe against race conditions that
could arise when other kernel components manipulate the list concurrently.
Functions
The kernel provides a number of auxiliary functions to manipulate and scan the data structures described
above. Essentially the kernel must be able to fulfill two different tasks:
- Given a local numerical ID and the corresponding namespace, find the task structure that is
described by this tuple. - Given a task structure, an ID type, and a namespace, obtain the local numerical ID.
Let us first concentrate on the case in which atask_structinstance must be converted into a numerical
ID. This is a two-step process:
- Obtain thepidinstance associated with the task structure. The auxiliary functionstask_pid,
task_tgid,task_pgrp,andtask_sessionare provided for the different types of IDs. This is
simple for PIDs:
static inline struct pid *task_pid(struct task_struct *task)
{
return task->pids[PIDTYPE_PID].pid;
}
Obtaining a TGID works similarly because it is nothing other than the PID of the tread group
leader. The element to grab istask->group_leader->pids[PIDTYPE_PID].pid.
Finding out a process group ID requires usingPIDTYPE_PGIDas array index. However, it
must again be taken from thepidinstance of the process group leader:
<sched.h>
static inline struct pid *task_pgrp(struct task_struct *task)
{
return task->group_leader->pids[PIDTYPE_PGID].pid;
}
- Once thepidinstance is available, the numerical ID can be read off from theuidinformation
available in thenumbersarray instruct pid:
kernel/pid.c
pid_t pid_nr_ns(struct pid pid, struct pid_namespace ns)
{
struct upid *upid;
pid_t nr = 0;
if (pid && ns->level <= pid->level) {
upid = &pid->numbers[ns->level];
if (upid->ns == ns)
nr = upid->nr;
}
return nr;
}