do

    技术2022-06-27  68

    1. 分配pid

    long pid = alloc_pidmap();

     

    2. 检查ptrace

        if (unlikely(current->ptrace)) { /*父进程被跟踪*/         trace = fork_traceflag (clone_flags);         if (trace)    /* 如果不是内核线程(no UNTRACED flag) */             clone_flags |= CLONE_PTRACE;     }

     

    3. 调用copy_process() 复制进程描述符

     

    4. 检查vfork flag. 如果是初始化vfork wait flag

            if (clone_flags & CLONE_VFORK) {             p->vfork_done = &vfork;             init_completion(&vfork);         }

     

    5. 检查是否pending

            if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {             /*              * We'll start up with an immediate SIGSTOP.              */             sigaddset(&p->pending.signal, SIGSTOP);             set_tsk_thread_flag(p, TIF_SIGPENDING);         }

     

    6. 检查stopped标志

    1). 如果没有设置stopped标志

            if (!(clone_flags & CLONE_STOPPED))             wake_up_new_task(p, clone_flags);

     

    2). stopped被设置             p->state = TASK_STOPPED;

     

    7. wake_up_new_task()

    1). 如果未设VM, 插子进程在父进程运行队列,恰好在父进程前面

            if (!(clone_flags & CLONE_VM)) {             /*              * The VM isn't cloned, so we're in a good position to              * do child-runs-first in anticipation of an exec. This              * usually avoids a lot of COW overhead.              */             if (unlikely(!current->array))                 __activate_task(p, rq);             else {                 p->prio = current->prio;                 list_add_tail(&p->run_list, ¤t->run_list); //前面                 p->array = current->array;                 p->array->nr_active++;                 rq->nr_running++;             }             set_need_resched();         }

    2). 否则不是同一cpu或者VM被设置,子进程插入父进程运行队列的队尾

    __activate_task(p, rq);

     

    8. 检查跟踪标志

            if (unlikely (trace)) {             current->ptrace_message = pid; /* pid存入message */

                ptrace_notify ((trace << 8) | SIGTRAP); /*SIGCHLD, 通知子进程的祖父进程(当前进程的父进程debugger), current创建了子进程,可以通过查找current->ptrace_message字段获得子进程的PID*/         }

     

    9. 如果设置VFORK, 把父插入等待队列,直到子进程释放自己的内存地址空间

     

    10. 结束返回子进程的pid


    最新回复(0)