????if (retval)
????goto bad_fork_cleanup_policy;
????retval = perf_event_init_task(p);
????if (retval)
????goto bad_fork_cleanup_policy;
????retval = audit_alloc(p);
????if (retval)
????goto bad_fork_cleanup_perf;
????/* copy all the process information */
????shm_init_task(p);
????retval = copy_semundo(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_audit;
????retval = copy_files(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_semundo;
????retval = copy_fs(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_files;
????retval = copy_sighand(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_fs;
????retval = copy_signal(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_sighand;
????retval = copy_mm(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_signal;
????retval = copy_namespaces(clone_flags?? p);
????if (retval)
????goto bad_fork_cleanup_mm;
????retval = copy_io(clone_flags?? p);
????//??????????????
????retval = copy_thread(clone_flags?? stack_start?? stack_size?? p);
????//??????????μ? pid
????if (pid != &init_struct_pid) {
????retval = -ENOMEM;
????pid = alloc_pid(p->nsproxy->pid_ns_for_children);
????if (!pid)
????goto bad_fork_cleanup_io;
????}
????//????????? pid 
????p->pid = pid_nr(pid);
????//……
????//??????? p
????return p;
???????? dup_task_struct ???????? task_struct
?????????????????????
?????????????????????????CPU ???????
???????? sched_fork ?????????????????????????????? TASK_RUNNING
???????????н?????????????????????????????????????????
???????? copy_thread ??????????????
??????????????????μ? pid
????dup_task_struct ????
????static struct task_struct *dup_task_struct(struct task_struct *orig)
????{
????struct task_struct *tsk;
????struct thread_info *ti;
????int node = tsk_fork_get_node(orig);
????int err;
????//??????? task_struct ???
????tsk = alloc_task_struct_node(node);
????if (!tsk)
????return NULL;
????//??????? thread_info ??????????????????ti ????
????ti = alloc_thread_info_node(tsk?? node);
????if (!ti)
????goto free_tsk;
????//?????????????????
????tsk->stack = ti;
????//……
????return tsk;
????}
????????alloc_task_struct_node??????? task_struct ???
????????alloc_thread_info_node??????? thread_info ????????????????thread_union?????壬????????? ti
????union thread_union {
????struct thread_info thread_info;
????unsigned long stack[THREAD_SIZE/sizeof(long)];
????};
??????????? ti ???????????
???????????dup_task_struct???????????tsk->stack?????????????????
????sched_fork ????
????core.c
????int sched_fork(unsigned long clone_flags?? struct task_struct *p)
????{
????unsigned long flags;
????int cpu = get_cpu();
????__sched_fork(clone_flags?? p);
????//?????????????? TASK_RUNNING
????p->state = TASK_RUNNING;
????//……
????//????????? CPU
????set_task_cpu(p?? cpu);
????put_cpu();
????return 0;
????}
??????????????sched_fork?????????????????????????????????????? TASK_RUNNING???????????? CPU
????copy_thread ????
????int copy_thread(unsigned long clone_flags?? unsigned long sp??
????unsigned long arg?? struct task_struct *p)
????{
????//???????????
????struct pt_regs *childregs = task_pt_regs(p);
????struct task_struct *tsk;
????int err;
????p->thread.sp = (unsigned long) childregs;
????p->thread.sp0 = (unsigned long) (childregs+1);
????memset(p->thread.ptrace_bps?? 0?? sizeof(p->thread.ptrace_bps));
????if (unlikely(p->flags & PF_KTHREAD)) {
????//??????
????memset(childregs?? 0?? sizeof(struct pt_regs));
????p->thread.ip = (unsigned long) ret_from_kernel_thread;
????task_user_gs(p) = __KERNEL_STACK_CANARY;
????childregs->ds = __USER_DS;
????childregs->es = __USER_DS;
????childregs->fs = __KERNEL_PERCPU;
????childregs->bx = sp; /* function */
????childregs->bp = arg;
????childregs->orig_ax = -1;
????childregs->cs = __KERNEL_CS | get_kernel_rpl();
????childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
????p->thread.io_bitmap_ptr = NULL;
????return 0;
????}
????//???????????????????????
????*childregs = *current_pt_regs();
????//????? eax ?? 0?????fork ??????????0
????childregs->ax = 0;
????if (sp)
????childregs->sp = sp;
????//?????ip ?????ret_from_fork???????????ret_from_fork??????
????p->thread.ip = (unsigned long) ret_from_fork;
????//……
????return err;
????}
????copy_thread ??δ????????????????????????????
??????????? fork ????????з???0???????childregs->ax = 0;??δ????????? eax ????0
?????????p->thread.ip = (unsigned long) ret_from_fork;???????? ip ????? ret_form_fork ??????????????????? ret_from_fork ?????е?
???????
???????????????????????
????dup_task_struct???????????μ???
??????????sched_fork?????????TASK_RUNNING
????copy_thread?н?????????????????????????????????????????????????μ?
??????ret_from_fork?????????eip????????
????????????ret_from_fork??????