ǰλ: Ͼվ > ϵͳ > Unix >

kernelѧϰ֮do_fork

ʱ:2016-02-10

Ͼվ www.sdguanhua.com ϴεϸĽ˼ϵͳնǵdo_forkʵ̵ֽĴdo_forkҪ˽ĴpidĴԼĿ

ϵԴ2.6.38.

Դ£

/* 
 *  Ok, this is the main fork-routine. 
 * 
 * It copies the process, and if successful kick-starts 
 * it and waits for it to finish using the VM if required. 
 */
  /*ⲿִ2.6.38ʵֵ*/
/*clone_flags͵һֽΪźָӽ˳ʱ 
*ӽ򸸽̷źͨsys_forksys_vfork֪ǵźžSIGCHLD 
*cloneûԼڵڶֱʾԴԱ־λforkΪ0vforkΪCLONE_VFORKCLONE_VM 
*cloneûԼ 
*/
long do_fork(unsigned long clone_flags,  
          unsigned long stack_start,  
          struct pt_regs *regs,  
          unsigned long stack_size,  
          int __user *parent_tidptr,  
          int __user *child_tidptr)  
{  
    /*һ*/
    struct task_struct *p;  
    int trace = 0;  
    long nr;//ӽ̺  
      
    /* 
     * Do some preliminary argument and permissions checking before we 
     * actually start allocating stuff 
     */
    /* 
    *һЩҪļ鹤ǻᷢsys_fork,sys_vfork,kernel_threadжûдCLONE_NEWUSERɼ 
    *ЩûִҪΪsys_cloneʹõ 
    */
    if (clone_flags & CLONE_NEWUSER) {  
        if (clone_flags & CLONE_THREAD)//ٱ־  
            return -EINVAL;  
        /* hopefully this check will go away when userns support is 
         * complete 
         */
        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||  
                !capable(CAP_SETGID))  
            return -EPERM;  
    }  
      
    /* 
     * We hope to recycle these flags after 2.6.26 
     */
     /*ЩҲǾһЩ鹤*/
    if (unlikely(clone_flags & CLONE_STOPPED)) {  
        static int __read_mostly count = 100;  
      
        if (count > 0 && printk_ratelimit()) {  
            char comm[TASK_COMM_LEN];  
      
            count--;  
            printk(KERN_INFO "fork(): process `%s' used deprecated "
                    "clone flags 0x%lx\n",  
                get_task_comm(comm, current),  
                clone_flags & CLONE_STOPPED);  
        }  
    }  
      
    /* 鿴Ŀྫݣhttp://www.sdguanhua.com/OS/unix/
     * When called from kernel_thread, don't do user tracing stuff. 
     */
    if (likely(user_mode(regs)))  
        trace = tracehook_prepare_clone(clone_flags);  
      
    /*copy_processɾ̵ĴϵͳԴḻɽĿȻ̺Ųͬ*/
    p = copy_process(clone_flags, stack_start, regs, stack_size,  
             child_tidptr, NULL, trace);  
    /* 
    *copy_processûָCLONE_STOPPEDͻwake_up_new_task½Ľ̷ŵ 
    *жӽͬһcpuûCLONE_VM־дʵƼӽ̷ŵ 
    *̵ǰӽ̵execͻһϵвҪĸƲ 
    */
    /* 
     * Do this prior waking up the new thread - the thread pointer 
     * might get invalid after that point, if the thread exits quickly. 
     */
     /*IS_ERR()жpǷȷ*/
    if (!IS_ERR(p)) {  
        /*ɹclone_flagsý״̬*/
        struct completion vfork;  
      
        trace_sched_process_fork(current, p);  
      
        nr = task_pid_vnr(p);  
              
        /* 
        *sys_fork,sys_vfork,kernel_threadûCLONE_PARENT_SETTIDparent_tidptr=NULL 
        *Ϊsys_cloneʹ 
        */
        if (clone_flags & CLONE_PARENT_SETTID)  
            put_user(nr, parent_tidptr);  
      
        /* 
        *sys_fork  sys_clone,˾ͰѸ̷Žȴ 
        */
        if (clone_flags & CLONE_VFORK) {  
            p->vfork_done = &vfork;  
            init_completion(&vfork);  
        }  
      
        audit_finish_fork(p);  
        tracehook_report_clone(regs, clone_flags, nr, p);  
      
        /* 
         * We set PF_STARTING at creation in case tracing wants to 
         * use this to distinguish a fully live task from one that 
         * hasn't gotten to tracehook_report_clone() yet.  Now we 
         * clear it and set the child going. 
         */
        p->flags &= ~PF_STARTING;  
      
        if (unlikely(clone_flags & CLONE_STOPPED)) {  
            /* 
             * We'll start up with an immediate SIGSTOP. 
             */
            sigaddset(&p->pending.signal, SIGSTOP);  
            set_tsk_thread_flag(p, TIF_SIGPENDING);  
            __set_task_state(p, TASK_STOPPED);  
        } else {  
            wake_up_new_task(p, clone_flags);  
        }  
      
        tracehook_report_clone_complete(trace, regs,  
                        clone_flags, nr, p);  
      
        if (clone_flags & CLONE_VFORK) {  
            freezer_do_not_count();  
            wait_for_completion(&vfork);//ȴ  
            freezer_count();  
            tracehook_report_vfork_done(p, nr);  
        }  
    } else {  
        nr = PTR_ERR(p);  
    }  
    return nr;  
}

.

Authorcsdn muge0913