分析进程调度时机

 

 

不同类型的进程有不同的调度需求

第一种分类:

I/O密集型,等待I/O的时间用来处理其他进程

CPU密集型

第二种分类

批处理进程:不必与用户交互,不用很快响应

实时进程:有实习需求,响应时间要短、要稳定

交互式进程:需要经常与用户交互,需要较长时间等待用户输入,响应时间要快,比如shell

 

linux支持普通的分时系统和实时系统

linux的调度基于分时和优先级。优先级是动态的,可以用设置nice。

进程调度通过schedule函数,进程调度的时机

1.中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();

2.内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;

3.用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度

 

中断保存上下文和进程保存上下文不同

中断:保存现场,恢复现场;在同一个进程中

进程:通过switch to的机制汇编实现;两个进程的切换

进程上下文包括:用户地址空间(程序代码、数据,用户堆栈等),控制信息(进程描述符、内核堆栈等),硬件上下文

 

进程调度通过schedule函数,下面分析schedule函数的执行过程

1 2865asmlinkage __visible void __sched schedule(void)//visible,表示在内核的部分都可以看到这个函数
2 2866{
3 2867    struct task_struct *tsk = current;
4 2868
5 2869    sched_submit_work(tsk);
6 2870    __schedule();
7 2871}

 调用__schedule

 1 static void __sched __schedule(void)
 2 2771{
 3 2772    struct task_struct *prev, *next;
 4 2773    unsigned long *switch_count;
 5 2774    struct rq *rq;
 6 2775    int cpu;
 7 2776
 8 2777need_resched:
 9 2778    preempt_disable();
10 2779    cpu = smp_processor_id();
11 2780    rq = cpu_rq(cpu);
12 2781    rcu_note_context_switch(cpu);
13 2782    prev = rq->curr;
14 2783
15 2784    schedule_debug(prev);
16 2785
17 2786    if (sched_feat(HRTICK))
18 2787        hrtick_clear(rq);
19 2788
20 2789    /*
21 2790     * Make sure that signal_pending_state()->signal_pending() below
22 2791     * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
23 2792     * done by the caller to avoid the race with signal_wake_up().
24 2793     */
25 2794    smp_mb__before_spinlock();
26 2795    raw_spin_lock_irq(&rq->lock);
27 2796
28 2797    switch_count = &prev->nivcsw;
29 2798    if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
30 2799        if (unlikely(signal_pending_state(prev->state, prev))) {
31 2800            prev->state = TASK_RUNNING;
32 2801        } else {
33 2802            deactivate_task(rq, prev, DEQUEUE_SLEEP);
34 2803            prev->on_rq = 0;
35 2804
36 2805            /*
37 2806             * If a worker went to sleep, notify and ask workqueue
38 2807             * whether it wants to wake up a task to maintain
39 2808             * concurrency.
40 2809             */
41 2810            if (prev->flags & PF_WQ_WORKER) {
42 2811                struct task_struct *to_wakeup;
43 2812
44 2813                to_wakeup = wq_worker_sleeping(prev, cpu);
45 2814                if (to_wakeup)
46 2815                    try_to_wake_up_local(to_wakeup);
47 2816            }
48 2817        }
49 2818        switch_count = &prev->nvcsw;
50 2819    }
51 2820
52 2821    if (task_on_rq_queued(prev) || rq->skip_clock_update < 0)
53 2822        update_rq_clock(rq);
54 2823
55 2824    next = pick_next_task(rq, prev);//选择下一个进程
56 2825    clear_tsk_need_resched(prev);
57 2826    clear_preempt_need_resched();
58 2827    rq->skip_clock_update = 0;
59 2828
60 2829    if (likely(prev != next)) {
61 2830        rq->nr_switches++;
62 2831        rq->curr = next;
63 2832        ++*switch_count;
64 2833
65 2834        context_switch(rq, prev, next); /* unlocks the rq */
66 2835        /*
67 2836         * The context switch have flipped the stack from under us
68 2837         * and restored the local variables which were saved when
69 2838         * this task called schedule() in the past. prev == current
70 2839         * is still correct, but it can be moved to another cpu/rq.
71 2840         */
72 2841        cpu = smp_processor_id();
73 2842        rq = cpu_rq(cpu);
74 2843    } else
75 2844        raw_spin_unlock_irq(&rq->lock);
76 2845
77 2846    post_schedule(rq);
78 2847
79 2848    sched_preempt_enable_no_resched();
80 2849    if (need_resched())
81 2850        goto need_resched;
82 2851}

 next = pick_next_task(rq, prev)指明下一个进程,其中的调度策略被封装了

 context_switch(rq, prev, next)用于完成上下文的切换

实验:函数进程调度分析调试

 

使用gdb调试,设置断点__schedule,context_switch,__switch_to

 

 执行到__schedule,根据next表示的进程,进行进程调用,通过context_switch切换上下文

switch_to函数切换堆栈等

posted @ 2015-04-26 17:10  蘑菇糖  阅读(869)  评论(0编辑  收藏  举报