分类: LINUX
2013-05-17 12:00:35
在进程创建的时候,Linux系统会分配一个号码给当前这个进程,这个号码在进程所在的命名空间中是唯一的,但在其它的兄弟进程中,这个号码就不是唯一的了,也就是对于全局的命名空间来说,这个号不是全局唯一。这个号码就是进程的ID号,简称为PID。
一,进程号数据结构表示
这个PID被保存在进程的结构表示task_struct中。
struct task_struct{
....
pid_t pid;
pid_t tgid;
.....
};
typedef int __kernel_pid_t; typedef __kernel_pid_t pid_t;
struct pid_namespace {
struct kref kref;
struct pidmap pidmap[PIDMAP_ENTRIES];
int last_pid;
struct task_struct *child_reaper;
struct kmem_cache *pid_cachep;
int level;
struct pid_namespace *parent;
#ifdef CONFIG_PROC_FS
struct vfsmount *proc_mnt;
#endif
};
struct upid {
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
int nr; //表示ID的数值,这个就是命名空间内所可见的PID数值。
struct pid_namespace *ns; // 该ID的命名空间指针。
struct hlist_node pid_chain; // 将所有的upid实例都保存在一散列溢出链表上。
};
struct pid
{
atomic_t count; // 引用计数
/* lists of tasks that use this pid */ //
struct hlist_head tasks[PIDTYPE_MAX]; // 每个数组项都是一个散列表头。
struct rcu_head rcu; //
int level;
struct upid numbers[1];
};
enum pid_type
{
PIDTYPE_PID,进程ID
PIDTYPE_PGID,进程组ID
PIDTYPE_SID,会话组ID
PIDTYPE_MAX
};
struct task_struct{
......
struct pid_link pids[PIDTYPE_MAX];
......
};
struct pid_link{ //定义于pid.h文件中。
struct hlist_node node;
struct pid *pid;
}
static struct hlist_head *pid_hash;
void __init pidhash_init(void)
{
int i, pidhash_size;
unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT);
pidhash_shift = max(4, fls(megabytes * 4));
pidhash_shift = min(12, pidhash_shift);
pidhash_size = 1 << pidhash_shift;
printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
pidhash_size, pidhash_shift,
pidhash_size * sizeof(struct hlist_head));
pid_hash = alloc_bootmem(pidhash_size * sizeof(*(pid_hash)));
if (!pid_hash)
panic("Could not alloc pidhash!\n");
for (i = 0; i < pidhash_size; i++)
INIT_HLIST_HEAD(&pid_hash[i]);
}
int fastcall attach_pid(struct task_struct *task, enum pid_type type,
struct pid *pid)
{
struct pid_link *link;
link = &task->pids[type];
link->pid = pid;
hlist_add_head_rcu(&link->node, &pid->tasks[type]);
return 0;
}
struct pid * fastcall find_pid_ns(int nr, struct pid_namespace *ns)
{
struct hlist_node *elem;
struct upid *pnr;
hlist_for_each_entry_rcu(pnr, elem,
&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);
struct task_struct *find_task_by_pid_type_ns(int type, int nr,
struct pid_namespace *ns)
{
return pid_task(find_pid_ns(nr, ns), type);
}
struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
{
struct task_struct *result = NULL;
if (pid) {
struct hlist_node *first;
first = rcu_dereference(pid->tasks[type].first);
if (first)
result = hlist_entry(first, struct task_struct, pids[(type)].node);
}
return result;
}
struct pid* _pid = task->pids[type].pid;
static int alloc_pidmap(struct pid_namespace *pid_ns)
{
int i, offset, max_scan, pid, last = pid_ns->last_pid;
struct pidmap *map;
pid = last + 1;
if (pid >= pid_max)
pid = RESERVED_PIDS;
offset = pid & BITS_PER_PAGE_MASK;
map = &pid_ns->pidmap[pid/BITS_PER_PAGE];
max_scan = (pid_max + BITS_PER_PAGE - 1)/BITS_PER_PAGE - !offset;
for (i = 0; i <= max_scan; ++i) {
if (unlikely(!map->page)) {
void *page = kzalloc(PAGE_SIZE, GFP_KERNEL);
/*
* Free the page if someone raced with us
* installing it:
*/
spin_lock_irq(&pidmap_lock);
if (map->page)
kfree(page);
else
map->page = page;
spin_unlock_irq(&pidmap_lock);
if (unlikely(!map->page))
break;
}
if (likely(atomic_read(&map->nr_free))) {
do {
if (!test_and_set_bit(offset, map->page)) {
atomic_dec(&map->nr_free);
pid_ns->last_pid = pid;
return pid;
}
offset = find_next_offset(map, offset);
pid = mk_pid(pid_ns, map, offset);
/*
* find_next_offset() found a bit, the pid from it
* is in-bounds, and if we fell back to the last
* bitmap block and the final block was the same
* as the starting point, pid is before last_pid.
*/
} while (offset < BITS_PER_PAGE && pid < pid_max &&
(i != max_scan || pid < last ||
!((last+1) & BITS_PER_PAGE_MASK)));
}
if (map < &pid_ns->pidmap[(pid_max-1)/BITS_PER_PAGE]) {
++map;
offset = 0;
} else {
map = &pid_ns->pidmap[0];
offset = RESERVED_PIDS;
if (unlikely(last == offset))
break;
}
pid = mk_pid(pid_ns, map, offset);
}
return -1;
}
static fastcall void free_pidmap(struct pid_namespace *pid_ns, int pid)
{
struct pidmap *map = pid_ns->pidmap + pid / BITS_PER_PAGE;
int offset = pid & BITS_PER_PAGE_MASK;
clear_bit(offset, map->page);
atomic_inc(&map->nr_free);
}
struct pid *alloc_pid(struct pid_namespace *ns)
{
struct pid *pid;
enum pid_type type;
int i, nr;
struct pid_namespace *tmp;
struct upid *upid;
pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
if (!pid)
goto out;
tmp = ns;
for (i = ns->level; i >= 0; i--) {//这里将对其可见的所有的命名空间都生成一个局部的ID
nr = alloc_pidmap(tmp);
if (nr < 0)
goto out_free;
pid->numbers[i].nr = nr;
pid->numbers[i].ns = tmp;
tmp = tmp->parent;
}
get_pid_ns(ns);
pid->level = ns->level;
atomic_set(&pid->count, 1);
for (type = 0; type < PIDTYPE_MAX; ++type)
INIT_HLIST_HEAD(&pid->tasks[type]);
spin_lock_irq(&pidmap_lock);
for (i = ns->level; i >= 0; i--) {//更新struct pid,对每个struct upid,都将其置于散列表上。
upid = &pid->numbers[i];
hlist_add_head_rcu(&upid->pid_chain,
&pid_hash[pid_hashfn(upid->nr, upid->ns)]);
}
spin_unlock_irq(&pidmap_lock);
out:
return pid;
out_free:
for (i++; i <= ns->level; i++)
free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
kmem_cache_free(ns->pid_cachep, pid);
pid = NULL;
goto out;
}
struct task_struct{
.......
struct task_struct *group_leader; /* threadgroup leader */
.......
};
from:http://blog.csdn.net/zmxiangde_88/article/details/8027431