《奔跑吧linux内核》3.3笔记,不足之处还望你们批评指正linux
根据实际物理属性,CPU域分类如图1所示。负载均衡
图1 CPU域分类函数
问题一:一个4核处理器中的每一个物理CPU拥有独立L1 cache且不支持超线程技术,分红两个簇cluster0和cluster1,每一个簇包含两个物理CPU核,簇中的CPU核共享L2cache。请画出该处理器在Linux内核里调度域和调度组的拓扑关系图。spa
4核处理器关系图如图2所示,在不支持超线程技术的状况下,每一个CPU核心只有一个执行线程,因此4核处理器没有SMT属性。cluster由两个CPU物理核组成,这两个CPU是MC层级且是兄弟关系。整个处理器能够看做DIE级别,所以该处理器只有两个层级,即MC和DIE。根据上述原则,画图图3所示上述4核处理器的调度域和调度组的拓扑关系图。线程
图2 4核处理器示意图3d
图3 4核处理器调度域和调度组的拓扑关系图blog
问题二:假设CPU0和CPU1同属于一个调度域中且它们都不是idle CPU,那么CPU1能够作负载均衡吗?进程
CPU1不能够作负载均衡,默认约定优先由调度域中第一个CPU作负载均衡。此时,只有CPU0能作负载均衡,或者当CPU0不是空闲CPU,CPU1处于idle状态,CPU1才能够作负载均衡。ci
问题三:如何查找出一个调度域里最繁忙的调度组?it
在find_busiest_group()函数中,简单概括步骤以下:
1)首先遍历该调度域中每一个调度组,计算各个调度组中的平均负载等相关信息;
2)根据平均负载,找出最繁忙的调度组;
3)获取本地调度组的平均负载(avg_load)和最繁忙调度组的平均负载,以及该调度域的平均负载;
4)本地调度组的平均负载大于最繁忙组的平均负载,或者本地调度组的平均负载大于调度域的平均负载,说明不适合作负载均衡,退出这次负载均衡处理;
5)根据最繁忙组的平均负载、调度域的平均负载和本地调度组的平均负载来计算该调度域的须要迁移的负载不均衡值。
问题四:若是一个调度域负载不平衡,请问如何计算须要迁移多少负载量呢?
计算方式如图4所示。当最繁忙的调度组合本地调度组都出现group_overloaded的状况下才会计算load_above_capacity,busiest.gcf指最繁忙调度组里的group_capacity_factor。公式查看最繁忙调度组的平均负载(组里每一个CPU的平均负载,不是组的总负载)和本地调度组的平均负载,以及整个调度域的平均负载的差值来计算该调度域的负载不均衡值(env->imbalance)。最后若是计算出来的不均衡值比最繁忙域里的每一个进程平均负载小,那么调用fix_small_imbalance()函数,该函数计算最小的不均衡值。(SCHED_CAPACITY_SCALE为1024)
图4 须要迁移的负载量的计算方式
问题五:使用内核提供的唤醒进程API,好比wake_up_process()来唤醒一个进程,那么进程唤醒后应该在哪一个CPU上运行呢?是调用wake_up_process()的那个CPU,仍是该进程以前运行的那个CPU,或者其余CPU呢?
唤醒CPU记做wakeup CPU,上次运行的CPU称为prev CPU。
若是设置了SD_BALANCE_WAKE,在select_idle_sibling()函数中,优先选择idle CPU。若是没有idle CPU,就只能选择wakeup CPU和prev CPU。当找到一个具备亲和性的调度域且wakeup CPU和prev CPU不是一个CPU,wake_affine()函数会从新计算wakeup CPU和prev CPU的负载状况,若是wakeup CPU的负载加上被唤醒进程的负载比prev CPU小,那么wakeup CPU能够唤醒进程,不然选择prev CPU。
对于没有设置SD_BALANCE_WAKE的状况,变量sd指系统调度域中和sd_flag有相同标志位的调度域,而后开始向下遍历查找最清闲的调度组和最清闲的CPU唤醒进程。