static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; prepare_to_copy(orig); tsk = alloc_task_struct(); if (!tsk) return NULL; ti = alloc_thread_info(tsk); if (!ti) { free_task_struct(tsk); return NULL; } *tsk = *orig; tsk->thread_info = ti; setup_thread_stack(tsk, orig); /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); tsk->btrace_seq = 0; tsk->splice_pipe = NULL; return tsk; }
static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; prepare_to_copy(orig); tsk = alloc_task_struct(); if (!tsk) return NULL; ti = alloc_thread_info(tsk); if (!ti) { free_task_struct(tsk); return NULL; } *ti = *orig->thread_info; *tsk = *orig; tsk->thread_info = ti; ti->task = tsk; /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); return tsk; }
static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; prepare_to_copy(orig); tsk = alloc_task_struct(); if (!tsk) return NULL; ti = alloc_thread_info(tsk); if (!ti) { free_task_struct(tsk); return NULL; } *tsk = *orig; tsk->stack = ti; setup_thread_stack(tsk, orig); #ifdef CONFIG_CC_STACKPROTECTOR tsk->stack_canary = get_random_int(); #endif /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); #ifdef CONFIG_BLK_DEV_IO_TRACE tsk->btrace_seq = 0; #endif tsk->splice_pipe = NULL; return tsk; }
static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; unsigned long *stackend; int err; prepare_to_copy(orig); tsk = alloc_task_struct(); if (!tsk) return NULL; ti = alloc_thread_info(tsk); if (!ti) { free_task_struct(tsk); return NULL; } err = arch_dup_task_struct(tsk, orig); if (err) goto out; tsk->stack = ti; err = prop_local_init_single(&tsk->dirties); if (err) goto out; setup_thread_stack(tsk, orig); clear_user_return_notifier(tsk); clear_tsk_need_resched(tsk); stackend = end_of_stack(tsk); *stackend = STACK_END_MAGIC; /* for overflow detection */ #ifdef CONFIG_CC_STACKPROTECTOR tsk->stack_canary = get_random_int(); #endif /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); #ifdef CONFIG_BLK_DEV_IO_TRACE tsk->btrace_seq = 0; #endif tsk->splice_pipe = NULL; account_kernel_stack(ti, 1); return tsk; out: free_thread_info(ti); free_task_struct(tsk); return NULL; }
static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; prepare_to_copy(orig); /* * 为新进程获取进程描述符 */ tsk = alloc_task_struct(); if (!tsk) return NULL; /* * 获取一片空闲区域4k或者8k, 用来存放新进程的thread_info结构和内核栈 */ ti = alloc_thread_info(tsk); if (!ti) { free_task_struct(tsk); return NULL; } /* * 将current进程描述符的内容复制到tsk所指向的task_struct结构中 */ *ti = *orig->thread_info; /* * 把current进程的thread_info描述符的内容复制到ti中 */ *tsk = *orig; /* * 下面两行将新进程的task_struct与thread_info绑定 */ tsk->thread_info = ti; ti->task = tsk; /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); return tsk; }
int import_thread_info(struct epm_action *action, ghost_t *ghost, struct task_struct *task) { struct thread_info *p; int r; p = alloc_thread_info(task); if (!p) { r = -ENOMEM; goto exit; } r = ghost_read(ghost, p, sizeof(struct thread_info)); /* Required by [__]free_thread_info() */ p->task = task; if (r) goto exit_free_thread_info; p->exec_domain = import_exec_domain(action, ghost); p->preempt_count = 0; p->addr_limit = USER_DS; r = import_restart_block(action, ghost, &p->restart_block); if (r) goto exit_free_thread_info; task->stack = p; exit: return r; exit_free_thread_info: __free_thread_info(p); goto exit; }
/* * 由do_fork()调用,为新的子进程创建task_struct, thread_info, 内核栈等信息 * 创建完成之后和父进程状态完全相同 */ static struct task_struct *dup_task_struct(struct task_struct *orig) { struct task_struct *tsk; struct thread_info *ti; unsigned long *stackend; int err; prepare_to_copy(orig); /* 申请task_struct内存空间 */ tsk = alloc_task_struct(); if (!tsk) return NULL; /* 申请thread_info内存空间 */ ti = alloc_thread_info(tsk); if (!ti) { /* 失败需要释放前面已经成功申请的task_struct内存空间,防止内存泄漏 */ free_task_struct(tsk); return NULL; } /* 复制orig进程的信息到tsk进程中,复制完成后地址空间地址相同 */ err = arch_dup_task_struct(tsk, orig); if (err) goto out; tsk->stack = ti; /* 清空新进程的部分标志 */ err = prop_local_init_single(&tsk->dirties); if (err) goto out; /* 新进程的进程栈信息 */ setup_thread_stack(tsk, orig); /* 清除进程栈的部分信息 */ clear_user_return_notifier(tsk); clear_tsk_need_resched(tsk); stackend = end_of_stack(tsk); *stackend = STACK_END_MAGIC; /* 用作内存越界检测 */ #ifdef CONFIG_CC_STACKPROTECTOR tsk->stack_canary = get_random_int(); #endif /* One for us, one for whoever does the "release_task()" (usually parent) */ atomic_set(&tsk->usage,2); atomic_set(&tsk->fs_excl, 0); #ifdef CONFIG_BLK_DEV_IO_TRACE tsk->btrace_seq = 0; #endif tsk->splice_pipe = NULL; /* 内核栈??? 干啥的??? */ account_kernel_stack(ti, 1); return tsk; out: free_thread_info(ti); free_task_struct(tsk); return NULL; }