Linux进程调度
来源:互联网 发布:手机制作遗像软件 编辑:程序博客网 时间:2024/05/16 06:27
说明如下引用代码对应的kernel版本是2.6.34
I. Linux进程调度的函数schedule,先看一下schedule的实现。
/* * schedule() is the main scheduler function. */asmlinkage void __sched schedule(void){struct task_struct *prev, *next;unsigned long *switch_count;struct rq *rq;int cpu;need_resched:preempt_disable();//禁止抢占,实际操作是将current_thread_info的preempt_count加1,其他进程/线程不会抢占当前线程了cpu = smp_processor_id();//获取当前CPU号,逻辑CPU号rq = cpu_rq(cpu); // 获取当前CPU的runqueue队列,该CPU上所有就绪状态的进程放在该队列中rcu_sched_qs(cpu); //prev = rq->curr;switch_count = &prev->nivcsw;release_kernel_lock(prev);//如果当前进程持有big kernel lock锁则释放,因为当前进程要切换出去了,不能占有该锁need_resched_nonpreemptible:schedule_debug(prev);if (sched_feat(HRTICK))hrtick_clear(rq);spin_lock_irq(&rq->lock);//runqueue队列加锁update_rq_clock(rq);clear_tsk_need_resched(prev);//清除标志TIF_NEED_RESCHED if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {/*如果当前进程非就绪,并且没有被抢占*/if (unlikely(signal_pending_state(prev->state, prev)))//如果当前进程是task_interruptible或者有信号送达,状态更改为就绪prev->state = TASK_RUNNING;elsedeactivate_task(rq, prev, 1); //将当前进程从就绪队列中摘除;非就绪进程怎么会在就绪队列中?就绪任务在获取锁或者主动睡眠时将任务状态修改为非就绪,但是没有立即从就绪队列中出队列,此时才出队列switch_count = &prev->nvcsw;}pre_schedule(rq, prev);if (unlikely(!rq->nr_running))//如果运行队列上进程数是0,则先通过idle_balance函数从其他CPU上调度,进行负载均衡idle_balance(cpu, rq); /*put_prev_task->put_prev_task_fair->put_prev_entity->__enqueue_entity将要调度出去的任务插入红黑树,当然插入红黑树的任务是R状态的,即没有被从就绪队列中摘除的*/ put_prev_task(rq, prev); next = pick_next_task(rq);//挑选下一个要运行的进程将其排进就绪队列,挑选原则是选择红黑树上的最左边节点进程 if (likely(prev != next)) { sched_info_switch(prev, next); perf_event_task_sched_out(prev, next, cpu); rq->nr_switches++;//队列切换次数更新 rq->curr = next; ++*switch_count;//进程切换次数更新 context_switch(rq, prev, next); /* unlocks the rq *///进程之间上下文切换 /* * the context switch might have flipped the stack from under * us, hence refresh the local variables. */ cpu = smp_processor_id(); rq = cpu_rq(cpu); } else spin_unlock_irq(&rq->lock); post_schedule(rq); if (unlikely(reacquire_kernel_lock(current) < 0)) goto need_resched_nonpreemptible; preempt_enable_no_resched(); if (need_resched())//如果该进程被其他进程设置了TIF_NEED_RESCHED标志,则函数重新执行进行调度 goto need_resched;}
可见schedule的作用是将当前进程从就绪队列摘除,从就绪队列中选择一个其他符合条件的进程调度运行。何谓符合条件,后面详细分解。其中if (prev->state && !(preempt_count() & PREEMPT_ACTIVE))条件判断中的抢占计数如果PREEMPT_ACTIVE置位对应场景是当前进程被抢占了,此时不再从就绪队列中摘除当前进程,直接调度当前进程释放CPU,以加快选择下一个进程。
II. 哪些场景调用schedule进行调度呢?即调度时机有哪些?汇总如下,后面针对每种场景结合代码分析。
1. 中断,异常
2. 进程退出,睡眠
3. 进程创建,被唤醒,优先级改变时
4. 进程阻塞,如阻塞在信号量,互斥锁
其中2是进程主动调度,其他是被动调度。
III. 概念辨析
1. 禁止抢占就是禁止调度吗?
看到许多资料提到禁止抢占就意味着禁止调度,何解?首先禁止抢占是针对进程(线程)来说的,所以标题的意思是禁止本进程的抢占意味着本进程不可调度了,和内核抢占配置CONFIG_PREEMPT宏不要混淆,配置宏打开意思是内核态可以抢占,是对所有进程而言的。进程A切换到进程B,有两种情况,一 A主动出让CPU 称作yielding,二 A被调度出让CPU称作preemption,两种都是调度,如果禁止抢占,即是禁止了preemption调度。
参考:http://blog.csdn.net/su_linux/article/details/15500053
http://blog.csdn.net/gatieme/article/details/51872618
- Linux 进程调度工具
- linux进程调度解析
- linux进程调度策略
- Linux 进程调度原理
- linux进程调度政策
- Linux进程调度时机
- Linux 进程调度机制
- Linux 进程调度原理
- linux进程调度方法
- Linux 进程调度原理
- linux 进程调度
- Linux 进程调度分析
- Linux 进程调度原理
- linux进程调度关键词
- linux进程调度浅析
- linux进程调度浅析
- linux进程调度
- linux进程调度
- 贫穷和懒惰是人生的耻辱
- 从开发转型到技术总监的迷茫
- Spring 初步
- 某生理检测仪对接(1)
- java programming basic knowledge--variable initialization
- Linux进程调度
- 扑克牌顺子
- [LeetCode]382. Linked List Random Node
- centos7上搭建php服务器环境
- myeclise10 svn: E210004: Number is larger than maximum
- openfire的session与路由机制(二)核心接口与类分析
- 51之数码管
- 关于LeetCode中Implement Queue using Stacks一题的理解
- web.xml配置详解