现在进程 1 所需要的我们都已经创建好了。可以说是万事俱备只欠东风!

那么怎么能让进程1运行呢,我们必须把进程1的进程描述符插入到 cpu 的活动运行队列中去,这样只要再调用 schedule() 那么进程1便可运行啦!废话少说马上进入 wake_up_new_task() 函数!

void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
{
    把新创建进程添加到 cpu 运行队列中去

    unsigned long flags;

    int this_cpu, cpu;

    runqueue_t *rq, *this_rq; 

    rq = task_rq_lock(p, &flags);
    锁住运行队列结构。并获得cpu运行队列指针!

    cpu = task_cpu(p);
    获得新创建进程的 cpu 编号

    this_cpu = smp_processor_id();
    获得当前cpu编号

    BUG_ON(p->state != TASK_RUNNING);

    /*
     * We decrease the sleep average of forking parents
     * and children as well, to keep max-interactive tasks
     * from forking tasks that are max-interactive. The parent
     * (current) is done further down, under its lock.
     */

    p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
        CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
    计算进程的平均睡眠值

    p->prio = effective_prio(p);
    设置进程的动态优先权(100-139)
    进程的静态优先级 static_prio 用于计算进程的时间片,而动态优先级作为调度器选择合适的进程的依据!

    if (likely(cpu == this_cpu)) {

        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, &current->run_list);

                p->array = current->array;

                p->array->nr_active++;

                rq->nr_running++;

            }

            set_need_resched();

        } else

            /* Run child last */
            __activate_task(p, rq);
            添加到runqueue中

        /*
         * We skip the following code due to cpu == this_cpu
         *
         *   task_rq_unlock(rq, &flags);
         *   this_rq = task_rq_lock(current, &flags);
         */

        this_rq = rq;

    } else {
        this_rq = cpu_rq(this_cpu);

        /*
         * Not the local CPU - must adjust timestamp. This should
         * get optimised away in the !CONFIG_SMP case.
         */

        p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
                    + rq->timestamp_last_tick;

        __activate_task(p, rq);

        if (TASK_PREEMPTS_CURR(p, rq))
            resched_task(rq->curr);

        /*
         * Parent and child are on different CPUs, now get the
         * parent runqueue to update the parent's ->sleep_avg:
         */

        task_rq_unlock(rq, &flags);

        this_rq = task_rq_lock(current, &flags);

    }

    current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
        PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);

    task_rq_unlock(this_rq, &flags);

}</pre>
<p></p>


<pre class="brush: cpp; title: ; notranslate" title=""> static inline runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
__acquires(rq-&gt;lock) {
struct runqueue *rq;

repeat_lock_task:

local_irq_save(*flags);

rq = task_rq(p);

spin_lock(&rq-&gt;lock);

if (unlikely(rq != task_rq(p))) {

    spin_unlock_irqrestore(&rq-&gt;lock, *flags);

    goto repeat_lock_task;

}

return rq; }

</pre>

<pre class="brush: cpp; title: ; notranslate" title=""> #define task_rq(p)      cpu_rq(task_cpu(p)) #define cpu_rq(cpu)     (&per_cpu(runqueues, (cpu)))

</pre>

取得每cpu变量per_cpu_runqueues本地拷贝的地址


</p>
<pre>
static inline unsigned int task_cpu(const struct task_struct *p)
{
    return p->thread_info->cpu;
}</pre>


</p>
<pre>
static int effective_prio(task_t *p)
{
    int bonus, prio;

    if (rt_task(p))
        return p->prio;
    首先判断是否为实时进程!(prio<100)

    bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
    获得创建进程的奖惩

    prio = p->static_prio - bonus;

    if (prio < MAX_RT_PRIO)
        prio = MAX_RT_PRIO;

    if (prio > MAX_PRIO-1)
        prio = MAX_PRIO-1;

    return prio;
}</pre>


</p>
<pre>
static inline void __activate_task(task_t *p, runqueue_t *rq)
{
    enqueue_task(p, rq->active);

    rq->nr_running++;
    更新队列中可运行进程数!
}</pre>


</p>
<pre>
static void enqueue_task(struct task_struct *p, prio_array_t *array)
{
    sched_info_queued(p);

    list_add_tail(&p->run_list, array->queue + p->prio);
    根据进程的动态优先级,把进程描述符添加到活动链表中!

    __set_bit(p->prio, array->bitmap);
    根据 prio 把 active 链表中相应进程位图置 1!位数代表优先级,表示此优先级有活动的进程!schedule() 函数正是根据位图中的哪位是1,到相应数组链表中去选择下一个要运行的进程!

    array->nr_active++;
    更新优先级链表中可运行进程数目!

    p->array = array;
    进程描述符中的array字段指向活动进程链表
}</pre>


至此,进程 1 成功创建完毕,但是创建归创建(只是创建了一些数据结构,并且添加到 cpu 运行队列中去),此时新创建的进程还没有运行,接下来就是 schedule() 这个主调度器的事情了 。。。。。。