Linux进程调度
A. linux采用了哪几种调度方法各用于哪类进程的调度
你问的是进程调度吧
Linux进程调度采用的是抢占式多任务处理,所以进程之间的挂起和继续运行无需彼此之间的协作。
调度方式:时间片,优先级,还有就是时间片加优先级混合,默认是第三种
B. Linux系统怎样执行进程调度
简单的说,就是执行schele()函数,具体的就复杂了,牵涉到算法(选择下一个执行进程)、进程切换等,要钻研一下才能懂,建议看下《深入理解LINUX内核》
C. linux 进程调度算法问题 主进程fork了 4个子进程a b c d 优先级相等 一种
cb这是第一个fork的子进程产生的第一个fork父进程进入elseif先执行子进程输出b这是第一个fork的父进程产生的父进程输出ab所以一共是三个进程父——>父(产生父子)父——>子(终)
D. 调度算法的linux进程调度算法
linux内核的三种调度方法:
1. SCHED_OTHER 分时调度策略,
2. SCHED_FIFO实时调度策略,先到先服务
3. SCHED_RR实时调度策略,时间片轮转
实时进程将得到优先调用,实时进程根据实时优先级决定调度权值,分时进程则通过nice和counter值决
定权值,nice越小,counter越大,被调度的概率越大,也就是曾经使用了cpu最少的进程将会得到优先调
度。
SHCED_RR和SCHED_FIFO的不同:
当采用SHCED_RR策略的进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列
尾保证了所有具有相同优先级的RR任务的调度公平。
SCHED_FIFO一旦占用cpu则一直运行。一直运行直到有更高优先级任务到达或自己放弃。
如果有相同优先级的实时进程(根据优先级计算的调度权值是一样的)已经准备好,FIFO时必须等待该
进程主动放弃后才可以运行这个优先级相同的任务。而RR可以让每个任务都执行一段时间。
SHCED_RR和SCHED_FIFO的相同点:
SHCED_RR和SHCED_FIFO都只用于实时任务。
创建时优先级大于0(1-99)。
按照可抢占优先级调度算法进行。
就绪态的实时任务立即抢占非实时任务。
所有任务都采用linux分时调度策略时。
1. 创建任务指定采用分时调度策略,并指定优先级nice值(-20~19)。
2. 将根据每个任务的nice值确定在cpu上的执行时间(counter)。
3. 如果没有等待资源,则将该任务加入到就绪队列中。
4. 调度程序遍历就绪队列中的任务,通过对每个任务动态优先级的计算(counter+20-nice)结果,选择
计算结果最大的一个去运行,当这 个时间片用完后(counter减至0)或者主动放弃cpu时,该任务将被放在
就绪队列末尾(时间片用完)或等待队列(因等待资源而放弃cpu)中。
5. 此时调度程序重复上面计算过程,转到第4步。
6. 当调度程序发现所有就绪任务计算所得的权值都为不大于0时,重复第2步。
所有任务都采用FIFO时:
1. 创建进程时指定采用FIFO,并设置实时优先级rt_priority(1-99)。
2. 如果没有等待资源,则将该任务加入到就绪队列中。
3. 调度程序遍历就绪队列,根据实时优先级计算调度权值(1000+rt_priority),选择权值最高的任务使用
cpu,该FIFO任务将一直占有cpu直到有优先级更高的任务就绪(即使优先级相同也不行)或者主动放弃(等
待资源)。
4. 调度程序发现有优先级更高的任务到达(高优先级任务可能被中断或定时器任务唤醒,再或被当前运行
的任务唤醒,等等),则调度程序立即在当前任务 堆栈中保存当前cpu寄存器的所有数据,重新从高优先级
任务的堆栈中加载寄存器数据到cpu,此时高优先级的任务开始运行。重复第3步。
5. 如果当前任务因等待资源而主动放弃cpu使用权,则该任务将从就绪队列中删除,加入等待队列,此时
重复第3步。
所有任务都采用RR调度策略时
1. 创建任务时指定调度参数为RR,并设置任务的实时优先级和nice值(nice值将会转换为该任务的时间片
的长度)。
2. 如果没有等待资源,则将该任务加入到就绪队列中。
3. 调度程序遍历就绪队列,根据实时优先级计算调度权值(1000+rt_priority),选择权值最高的任务使用
cpu。
4. 如果就绪队列中的RR任务时间片为0,则会根据nice值设置该任务的时间片,同时将该任务放入就绪队
列的末尾。重复步骤3。
5. 当前任务由于等待资源而主动退出cpu,则其加入等待队列中。重复步骤3。
系统中既有分时调度,又有时间片轮转调度和先进先出调度
1. RR调度和FIFO调度的进程属于实时进程,以分时调度的进程是非实时进程。
2. 当实时进程准备就绪后,如果当前cpu正在运行非实时进程,则实时进程立即抢占非实时进程。
3. RR进程和FIFO进程都采用实时优先级做为调度的权值标准,RR是FIFO的一个延伸。FIFO时,如果两
个进程的优先级一样,则这两个优先 级一样的进程具体执行哪一个是由其在队列中的未知决定的,这样导
致一些不公正性(优先级是一样的,为什么要让你一直运行?),如果将两个优先级一样的任务 的调度策略都
设为RR,则保证了这两个任务可以循环执行,保证了公平。
E. linux进程调度的三种策略是什么
进程调度策略就是调度系统种哪一个进程来CPU运行。这种调度分2层考虑。 第一层,进程状态这个是最优先考虑的,也就是说优先级最高的。在linux中只有就绪态的进程才有可能会被调度选中然后占有CPU,其它状态的进程不可能占有的到CPU。下面是linux中进程的状态TASK_RUNNING:就绪状态,得到CPU就可以运行。
TASK_INTERRUPTIBLE:浅度睡眠,资源到位或者受到信号就会变成就绪态。
TASK_UNINTERRUPTIBLE:深度睡眠,资源到位就会进入就绪态,不响应信号。
TASK_ZOMBIE:僵死态,进程exit后。
TASK_STOPPED:暂停态,收到SIG_CONT信号进入就绪态。 第二层,其实真正在操作系统中的实现,就是所有就绪态进程链接成一个队列,进程调度时候只会考虑这个队列中的进程,对其它的进程不考虑,这就实现了第一层中的要求。接下来就是就绪队列内部各个进程的竞争了。 Linux采用3种不同的调度政策,SCHED_FIFO(下面简写成FIFO,先来先服务),SCHED_RR(简写成RR,时间片轮流),SCHED_OTHER(下面简写成OTHER)。这里大家就能看出一个问题,采用同等调度政策的进程之间自然有可比性,Linux3种调度政策并存,那么不同调度政策间的进程如何比较呢?可以说他们之间根本就没有可比性。其实在调度时候,调度只看一个指标,那就是各个进程所具有的权值,权值最大的且在可执行队列中排在最前面的就会被调度执行。而权值的计算才会设计到各方面因素,其中调度政策可以说在计算权值中,份量是最重的。 为什么Linux要这么干呢?这是由于事务的多样性决定的,进程有实时性进程和非实时性的进程2种,FIFO和RR是用来支持实时性进程的调度,我们看一下这3种政策下权值的计算公式就明白了:FIFO和RR计算公式,权值=1000+进程真正的运行时间OTHER计算公式,当时间片为0时,权值=0.当时间片不为0时候,权值=剩余时间片+20-nice,同时如果是内核线程有+1的小加分,这是因为内核线程无需用户空间的切换,所以给它加了一分,奖励他在进程切换时候开销小的功劳。时间片好理解,那么nice这个值,用过linux系统的人都知道,这是一个从unix下继承过来的概念,表示谦让度,是一个从20~-19的数,可以通过nice和renice指令来设置。从代码中也能看到值越小就越不会谦让他人。 从这里我们看出FIFO和RR至少有1000的基数,所以在有FIFO和RR调度政策进程存在时,OTHER进程是没有机会被调度的到的。从权值计算公式同时也能看出,FIFO先来先服务的调度政策满足了,但RR这个时间片轮流的调度如果按照这种权值计算是不能满足时间片轮流这一概念的。这里只是权值的计算,在调度时候对RR政策的进程特殊处理。 以上都是权值计算,下面看看真正的调度过程,首先是对RR政策进程的特殊处理,如果当前进程采用的RR政策,那么看他的时间片是否用完,用完了就踢到就绪队列尾部,同时恢复他的时间片。然后是便利整个就绪队列,找到第一个权值最大的进程来运行。 整体调度效果就是:如果有FIFO和RR政策的进程,就优先调度他们2个,他们之间看已执行时间长短决定胜负,而2种政策内部则遵守各自调度政策。而OTHER只有在前面2种不存在于就绪队列时候才有可能执行,他们实际也是轮流执行,但他们之间是靠剩余时间和NICE值来决定胜负。同时就绪队列中排在最前面的最优先考虑在同样权值情况下。
F. linux调度是基于进程还是线程
在LINUX系统之中,被调度的应该是进程。因为只有进程才拥有一个独立的上下文环境,是分配系统资源的最小单位……而线程在SMP体系中加速了执行的效率……
在LINUX之中,线程也可称作轻量级进程,它能享有自己的堆栈,线程ID等独立资源,但大多还是要依赖其创建进程,比如地址空间,信号,文件句柄……
G. linux操作系统进程调度
Linux进程调度采用的是抢占式多任务处理,所以进程之间的挂起和继续运行无需彼此之间的协作。
H. 请教linux下用户态进程调度问题
在进行Linux系统操作的时候,有时候会遇到一次用户态进程死循环,即系统反应迟钝、进程挂死等问题,那么遇到这些问题又该如何解决呢?下面小编就给大家介绍下一次用户态进程死循环的问题该如何处理。
Linux下如何处理一次用户态进程死循环问题
1、问题现象
业务进程(用户态多线程程序)挂死,操作系统反应迟钝,系统日志没有任何异常。从进程的内核态堆栈看,看似所有线程都卡在了内核态的如下堆栈流程中:
[root@vmc116 ~]# cat /proc/27007/task/11825/stack
[《ffffffff8100baf6》] retint_careful+0x14/0x32
[《ffffffffffffffff》] 0xffffffffffffffff
2、问题分析
1)内核堆栈分析
从内核堆栈看,所有进程都阻塞在 retint_careful上,这个是中断返回过程中的流程,代码(汇编)如下:
entry_64.S
代码如下:
ret_from_intr:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
/* Restore saved previous stack */
popq %rsi
CFI_DEF_CFA rsi,SS+8-RBP /* reg/off reset after def_cfa_expr */
leaq ARGOFFSET-RBP(%rsi), %rsp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET
。。。
retint_careful:
CFI_RESTORE_STATE
bt $TIF_NEED_RESCHED,%edx
jnc retint_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
pushq_cfi %rdi
SCHEDULE_USER
popq_cfi %rdi
GET_THREAD_INFO(%rcx)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
jmp retint_check
这其实是用户态进程在用户态被中断打断后,从中断返回的流程,结合retint_careful+0x14/0x32,进行反汇编,可以确认阻塞的点其实就在
SCHEDULE_USER
这其实就是调用schele()进行调度,也就是说当进程走到中断返回的流程中时,发现需要调度(设置了TIF_NEED_RESCHED),于是在这里发生了调度。
有一个疑问:为什么在堆栈中看不到schele()这一级的栈帧呢?
因为这里是汇编直接调用的,没有进行相关栈帧压栈和上下文保存操作。
2)进行状态信息分析
从top命令结果看,相关线程实际一直处于R状态,CPU几乎完全耗尽,而且绝大部分都消耗在用户态:
[root@vmc116 ~]# top
top - 09:42:23 up 16 days, 2:21, 23 users, load average: 84.08, 84.30, 83.62
Tasks: 1037 total, 85 running, 952 sleeping, 0 stopped, 0 zombie
Cpu(s): 97.6%us, 2.2%sy, 0.2%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32878852k total, 32315464k used, 563388k free, 374152k buffers
Swap: 35110904k total, 38644k used, 35072260k free, 28852536k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27074 root 20 0 5316m 163m 14m R 10.2 0.5 321:06.17 z_itask_templat
27084 root 20 0 5316m 163m 14m R 10.2 0.5 296:23.37 z_itask_templat
27085 root 20 0 5316m 163m 14m R 10.2 0.5 337:57.26 z_itask_templat
27095 root 20 0 5316m 163m 14m R 10.2 0.5 327:31.93 z_itask_templat
27102 root 20 0 5316m 163m 14m R 10.2 0.5 306:49.44 z_itask_templat
27113 root 20 0 5316m 163m 14m R 10.2 0.5 310:47.41 z_itask_templat
25730 root 20 0 5316m 163m 14m R 10.2 0.5 283:03.37 z_itask_templat
30069 root 20 0 5316m 163m 14m R 10.2 0.5 283:49.67 z_itask_templat
13938 root 20 0 5316m 163m 14m R 10.2 0.5 261:24.46 z_itask_templat
16326 root 20 0 5316m 163m 14m R 10.2 0.5 150:24.53 z_itask_templat
6795 root 20 0 5316m 163m 14m R 10.2 0.5 100:26.77 z_itask_templat
27063 root 20 0 5316m 163m 14m R 9.9 0.5 337:18.77 z_itask_templat
27065 root 20 0 5316m 163m 14m R 9.9 0.5 314:24.17 z_itask_templat
27068 root 20 0 5316m 163m 14m R 9.9 0.5 336:32.78 z_itask_templat
27069 root 20 0 5316m 163m 14m R 9.9 0.5 338:55.08 z_itask_templat
27072 root 20 0 5316m 163m 14m R 9.9 0.5 306:46.08 z_itask_templat
27075 root 20 0 5316m 163m 14m R 9.9 0.5 316:49.51 z_itask_templat
。。。
3)进程调度信息
从相关线程的调度信息看:
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15681811525768 129628804592612 3557465
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15682016493013 129630684625241 3557509
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15682843570331 129638127548315 3557686
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15683323640217 129642447477861 3557793
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
15683698477621 129645817640726 3557875
发现相关线程的调度统计一直在增加,说明相关线程一直是在被调度运行的,结合其状态也一直是R,推测很可能在用户态发生了死循环(或者非睡眠死锁)。
这里又有问题:为什么从top看每个线程的CPU占用率只有10%左右,而不是通常看到的死循环进程导致的100%的占用率?
因为线程数很多,而且优先级都一样,根据CFS调度算法,会平均分配时间片,不会让其中一个线程独占CPU。结果为多个线程间轮流调度,消耗掉了所有的cpu。。
另一个问题:为什么这种情况下,内核没有检测到softlockup?
因为业务进程的优先级不高,不会影响watchdog内核线程(最高优先级的实时线程)的调度,所以不会产生softlockup的情况。
再一个问题:为什么每次查看线程堆栈时,总是阻塞在retint_careful,而不是其它地方?
因为这里(中断返回的时候)正是调度的时机点,在其它时间点不能发生调度(不考虑其它情况~),而我们查看线程堆栈的行为,也必须依赖于进程调度,所以我们每次查看堆栈时,正是查看堆栈的进程(cat命令)得到调度的时候,这时正是中断返回的时候,所以正好看到的阻塞点为retint_careful。
4)用户态分析
从上面的分析看,推测应该是用户态发生了死锁。
用户态确认方法:
部署debug信息,然后gdb attach相关进程,确认堆栈,并结合代码逻辑分析。
最终确认该问题确为用户态进程中产生了死循环。
I. 当前linux内核的进程调度,时间片究竟是多长时间
有个叫 HZ 的设置, 是编译内核的时候选定的。 比如HZ是1000, 就是一秒钟轮换1000次。