全部博文(16)
分类: LINUX
2010-08-11 20:56:13
重头戏来了!copy_process() 函数完成父进程描述符中相关资源到子进程中的复制工作,并对关键资源进行了修改,以标识新生成的子进程!
由于此函数非常之长,在此就不列出完整源代码,只对关键部分进行分析!
Let’s go!
static task_t *copy_process(unsigned long clone_flags,unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr,
int pid)
首先对参数 clone_flags 的合理性进行验证!
p = dup_task_struct(current);
复制一份当前进程的描述符的拷贝!
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
struct thread_info *ti;
prepare_to_copy(orig);
在当前进程使用FPU的情况下,保存当前进程的FPU上下文内容到进程的成员变量 thread_info 中
tsk = alloc_task_struct();
申请sizeof(struct task_struct) 大小内存空间,用作新创建进程的进程描述符!
# define alloc_task_struct() kmem_cache_alloc(task_struct_cachep,GFP_KERNEL)
从task_struct_cachep 高速缓存描述符中分配一个对象!
在 fork_init() 函数中 已经创建好了task_struct 结构专用的缓冲队列!
if (!tsk)
return NULL;
ti = alloc_thread_info(tsk);
为新创建的进程申请 thread_info 结构所需的内存空间!
#define alloc_thread_info(tsk) \
({ \
struct thread_info *ret; \
\
ret = kmalloc(THREAD_SIZE, GFP_KERNEL); \
if (ret) \
memset(ret, 0, THREAD_SIZE); \
ret; \
})
从普通缓存中申请thread_info 大小的内存空间,并清0
if (!ti) {
free_task_struct(tsk);
return NULL;
}
*ti = *orig->thread_info;
将当前进程的thread_info 结构中内容赋值给新创建的进程的thread_info结构中(进程1)!
*tsk = *orig;
同样道理赋值task_struct 结构
tsk->thread_info = ti;
修改新创建进程进程描述符的thread_info字段,使其指向新创建的thread_info结构!
ti->task = tsk;
同样道理修改thread_info结构的 task 字段使其指向 tss_struct 结构!
/* One for us, one for whoever does the "release_task()" (usually parent) */
atomic_set(&tsk->usage,2);
设置新创建子进程的进程描述符的引用计数usage为2。其中一个代表本进程对该进程描述符的引用计数;另一个是父进程的引用计数
return tsk;
}