首页 > 系统相关 >linux内核源码阅读(四)Linux进程调度时机

linux内核源码阅读(四)Linux进程调度时机

时间:2022-12-21 12:08:04浏览次数:43  
标签:调用 函数 中断 linux 调度 源码 Linux 进程 时钟


调度程序虽然特别重要,但它不过是一个存在于内核空间中的函数而已,并不神秘。Linux的调度程序是一个叫Schedule()的函数,这个函数被调用的频率很高,由它来决定是否要进行进程的切换,如果要切换的话,切换到哪个进程等等。我们先来看在什么情况下要执行调度程序,我们把这种情况叫做调度时机。

Linux调度时机主要有:

1、进程状态转换的时刻:进程终止、进程睡眠;

2、当前进程的时间片用完时(current->counter=0);

3、设备驱动程序

4、进程从中断、异常及系统调用返回到用户态时;

时机1,进程要调用sleep()或exit()等函数进行状态转换,这些函数会主动调用调度程序进行进程调度;

时机2,由于进程的时间片是由时钟中断来更新的,因此,这种情况和时机4是一样的。

时机3,当设备驱动程序执行长而重复的任务时,直接调用调度程序。在每次反复循环中,驱动程序都检查need_resched的值,如果必要,则调用调度程序schedule()主动放弃CPU。

时机4,如前所述,不管是从中断、异常还是系统调用返回,最终都调用ret_from_sys_call(),由这个函数进行调度标志的检测,如果必要,则调用调用调度程序。那么,为什么从系统调用返回时要调用调度程序呢?这当然是从效率考虑。从系统调用返回意味着要离开内核态而返回到用户态,而状态的转换要花费一定的时间,因此,在返回到用户态前,系统把在内核态该处理的事全部做完。

对于直接执行调度程序的时机,我们不讨论,因为后面我们将会描述调度程序的工作过程。前面我们讨论了时钟中断,知道了时钟中断的重要作用,下面我们就简单看一下每个时钟中断发生时内核要做的工作,首先对这个最频繁的调度时机有一个大体了解,然后再详细讨论调度程序的具体工作过程。

每个时钟中断(timer interrupt)发生时,由三个函数协同工作,共同完成进程的选择和切换,它们是:schedule()、do_timer()及ret_form_sys_call()。我们先来解释一下这三个函数:

schedule():进程调度函数,由它来完成进程的选择(调度);

do_timer():暂且称之为时钟函数,该函数在时钟中断服务程序中被调用,是时钟中断服务程序的主要组成部分,该函数被调用的频率就是时钟中断的频率即每秒钟100次(简称100赫兹或100Hz);

ret_from_sys_call():系统调用返回函数。当一个系统调用或中断完成时,该函数被调用,用于处理一些收尾工作,例如信号处理、核心任务等等。

这三个函数是如何协调工作的呢?

前面我们看到,时钟中断是一个中断服务程序,它的主要组成部分就是时钟函数do_timer(),由这个函数完成系统时间的更新、进程时间片的更新等工作,更新后的进程时间片counter作为调度的主要依据。

在时钟中断返回时,要调用函数ret_from_sys_call(),前面我们已经讨论过这个函数,在这个函数中有如下几行:

cmpl $0, _need_resched

jne reschedule

     ……

restore_all:

     RESTORE_ALL

  

reschedule:

     call SYMBOL_NAME(schedule)    

     jmp ret_from_sys_call

 

这几行的意思很明显:检测 need_resched 标志,如果此标志为非0,那么就转到reschedule处调用调度程序schedule()进行进程的选择。调度程序schedule()会根据具体的标准在运行队列中选择下一个应该运行的进程。当从调度程序返回时,如果发现又有调度标志被设置,则又调用调度程序,直到调度标志为0,这时,从调度程序返回时由RESTORE_ALL恢复被选定进程的环境,返回到被选定进程的用户空间,使之得到运行。

以上就是时钟中断这个最频繁的调度时机。讨论这个的主要目的使读者对时机4有个大致的了解。

最后要说明的是,系统调用返回函数ret_from_sys_call()是从系统调用、异常及中断返回函数通常要调用的函数,但并不是非得调用,对于那些要经常被响应的和要被尽快处理的中断请求信号,为了减少系统开销,处理完成后并不调用 ret_from_sys_call()(因为很显然的,从这些中断处理程序返回到的用户空间肯定是那个被中断的进程,无需重新选择),并且,它们作的工作要尽可能少,因为响应的频率太高了。

Linux 调度程序和其他的UNIX调度程序不同,尤其是在“nice level”优先级的处理上,与优先权调度(priority高的进程最先运行)不同,Linux用的是时间片轮转调度(Round Robing),但同时又保证了高优先级的进程运行的既快、时间又长(both sooner and longer)。而标准的UNIX调度程序都用到了多级进程队列。大多数的实现都用到了二级优先队列:一个标准队列和一个实时(“real time”)队列。一般情况下,如果实时队列中的进程未被阻塞,它们都要在标准队列中的进程之前被执行,并且,每个队列中,“nice level”高的进程先被执行。

总体上,Linux 调度序程在交互性方面表现很出色,当然了,这是以牺牲一部分“吞吐量”为代价的。

标签:调用,函数,中断,linux,调度,源码,Linux,进程,时钟
From: https://blog.51cto.com/u_11970680/5959676

相关文章

  • MyBatis源码分析(二)prepareStatement预编译的执行流程
    通常我们如果自己写建立数据库连接的代码的时候,都会这么写pstmt=conn.prepareStatement(sql);pstmt.setString(1,email);result=pstmt.executeQuery();而Mybatis是怎么......
  • JDK源码之CompletableFuture(二)链式调用原理
    ​​JDK源码之CompletableFuture(一)结果返回原理​​JDK源码之CompletableFuture(二)链式调用原理JDK源码之CompletableFuture(三)anyOf,allOf是怎么实现的?目录​​一、第一步调......
  • SpringMVC父子容器加载与关系源码
    我们都知道SpringMVC父子容器加载是通过dispatcherServlet与ContextLoaderListener类:他们的关系源码如下:先说父容器加载:Context'Loader'Listener源码如下:@Overridepublic......
  • AliMQ(RocketMQ)源码(一)创建producer
    公司现在在使用阿里云的AliMQ也就是RocketMQ,趁着工作之余,将RocketMQ的使用心得分析一下,关于RocketMQ的Producer、Consumer、Broker、NameServer等架构问题,在此处先不做分析......
  • AliMQ(RocketMQ)源码(二)producer.start()
    在创建完成Producer后,就进入了Producer的start()方法。start()方法DefaultMQProducerImpl的start()方法。this.serviceState=ServiceState.START_FAILED;......
  • linux远程连接注意防火墙
    当我们远程连接linux服务器的时候,有时候会遇到连接不上服务器的情况,在确定一切都没问题的时候,那很可能就是防火墙开启了,此时我们只要关闭防火墙就行了。命令如下:serviceipt......
  • Wallys//AX200NGW,adapter card with one M.2 slot/DR2g41 Linux,WiFi-modules,4-mini
    DR3g11//1xM.2Card,QCN9074,AX200NGWAdapterCardsupportDR9074-6E DR2g41//Linux,WiFi-modules,4-miniPCIE-slotAdapterCard4xMiniPCIeCard4xM.2Ca......
  • linux网络配置
    centos7环境cd/etc/sysconfig/network-scripts这里查看文件是 ifcfg-eno1viifcfg-eno1这里编辑如下TYPE=EthernetPROXY_METHOD=noneBROWSER_ONLY=noBOOTPR......
  • Linux服务搭建--DHCP
    1.什么是DHCP服务?DHCP(动态主机配置协议):是局域网常见的网络协议,它主要是通过客户端发送广播数据包给整个物理网段内的所有主机,若局域网内存在DHCP服务器,该服务器收到广播包,才......
  • Linux负载均衡解决方案 -- LVS 理论概述
    Lvs理论概述​​一、什么是LVS?​​​​二、为什么需要LVS?​​​​三、LVS原理​​​​1、LVS体系结构​​​​2、LVS工作模式​​​​3、LVS调度算法​​​​四、L......