From c7a5dc2f87e7086c51baae7e3edabd5be28531e6 Mon Sep 17 00:00:00 2001 From: Cheng Jian Date: Fri, 5 Jul 2019 20:31:09 +0800 Subject: [PATCH] update schedule 09-tuning --- study/driver/00-code/hello/Makefile | 2 +- study/driver/00-code/hello/hello.c | 25 --- .../05-schedule/09-tuning/README.md | 165 +++++++++++++++++- .../10-group/002-bandwidth/README.md | 37 ++++ study/kernel/10-bpf/01-mybcc/hello_world.py | 1 + study/kernel/12-ftrace/00-use/README.md | 36 ++++ study/kernel/12-ftrace/README.md | 35 ++++ 7 files changed, 273 insertions(+), 28 deletions(-) create mode 100644 study/kernel/01-process/05-schedule/10-group/002-bandwidth/README.md create mode 100644 study/kernel/12-ftrace/00-use/README.md create mode 100644 study/kernel/12-ftrace/README.md diff --git a/study/driver/00-code/hello/Makefile b/study/driver/00-code/hello/Makefile index 5ffdb3f..d54489c 100644 --- a/study/driver/00-code/hello/Makefile +++ b/study/driver/00-code/hello/Makefile @@ -32,7 +32,7 @@ else # userspace LINUX_KERNEL := $(shell uname -r) -LINUX_KERNEL_PATH := /lib/modules/$(LINUX_KERNEL)/build +LINUX_KERNEL_PATH ?= /lib/modules/$(LINUX_KERNEL)/build CURRENT_PATH := $(shell pwd) CFG_INC := $(CURRENT_PATH) diff --git a/study/driver/00-code/hello/hello.c b/study/driver/00-code/hello/hello.c index c456dfb..3f17770 100644 --- a/study/driver/00-code/hello/hello.c +++ b/study/driver/00-code/hello/hello.c @@ -11,32 +11,8 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Gatieme"); MODULE_DESCRIPTION("hello world"); -/* - * print the module information - */ -static void print_module(void) -{ - struct module *mod; - - printk(KERN_ALERT "this module: %p==%p\n", &__this_module, THIS_MODULE); - printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state); - printk(KERN_ALERT "module name: %s\n", THIS_MODULE->name); - - list_for_each_entry(mod, *(&THIS_MODULE->list.prev), list); - printk(KERN_ALERT "module name: %s\n", mod->name); - printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state); -} - - static int hello_init(void) { - print_module( ); - - printk(KERN_ALERT "run in cpu %d\n", get_cpu()); - - printk(KERN_ALERT "PAGE_OFFSET : 0x%lx, TASK_SIZE : 0x%lx", PAGE_OFFSET, TASK_SIZE); - - return 0; } @@ -44,7 +20,6 @@ static int hello_init(void) static void hello_exit(void) { - printk(KERN_ERR"exit"); } diff --git a/study/kernel/01-process/05-schedule/09-tuning/README.md b/study/kernel/01-process/05-schedule/09-tuning/README.md index 7f6fc93..8cac06a 100644 --- a/study/kernel/01-process/05-schedule/09-tuning/README.md +++ b/study/kernel/01-process/05-schedule/09-tuning/README.md @@ -2209,7 +2209,7 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) } ``` -* 当内核 [`pick_next_entity`](https://elixir.bootlin.com/linux/v4.14.4/source/kernel/sched/fair.c#L3958) 将调度实体 `se` 优选出来作为下一个进程的时候, 就需要清除之前对该实体的 `buddy` 标记. +* 当内核 [`pick_next_entity`](https://elixir.bootlin.com/linux/v4.14.4/source/kernel/sched/fair.c#L3958) 将调度实体 `se` 优选出来作为下一个进程的时候, 就需要清除之前对该实体的 `buddy` 标记. 因为该进程很有可能是因为自己是 `last-buddy` 或者 `next-buudy` 而优选出来的. 这时候清除 `buddy` 信息. 从而不会对下次优选 在进行影响. 有利于调度器的公平性和正常运作.参见 [`pick_next_entity`](https://elixir.bootlin.com/linux/v4.14.4/source/kernel/sched/fair.c#L3958) @@ -2281,7 +2281,7 @@ pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr) 当前如果是通过 `yield` 放弃的 `CPU`, 则在设置下一个调度实体之前也要清除之前的 `buddies` 的设置. ```cpp -// +// static void yield_task_fair(struct rq *rq) { // ...... @@ -2297,8 +2297,169 @@ static void yield_task_fair(struct rq *rq) ###11.5.1 `CACHE_HOT_BUDDY` ------- + 调度器调度和选核的时候有一项重要的参考就是 `cache-hot` +load_balance 在做负载均衡的时候, can_migrate_task 判断一个进程是否可以从 env->src +迁移到 env->dst 的关键指标就是 task_hot. + + +```cpp +load_balance +-=> detach_tasks + -=>can_migrate_task + -=>task_hot +``` + + +关于 cache-hot 的判断, 最关键的指标是 `sysctl_sched_migration_cost`, 参照第 7 节的描述. +但是如果开启了 CACHE_HOT_BUDDY, 那么调度器会认为 CFS_RQ 上 LAST_BUDDY 和 NEXT_BUDDY +也是 cache-hot 的. + +```cpp +/* + * Is this task likely cache-hot: + */ +static int task_hot(struct task_struct *p, struct lb_env *env) +{ + s64 delta; + + lockdep_assert_held(&env->src_rq->lock); + + if (p->sched_class != &fair_sched_class) + return 0; + + if (unlikely(p->policy == SCHED_IDLE)) + return 0; + + /* + * Buddy candidates are cache hot: + */ + if (sched_feat(CACHE_HOT_BUDDY) && env->dst_rq->nr_running && + (&p->se == cfs_rq_of(&p->se)->next || + &p->se == cfs_rq_of(&p->se)->last)) + return 1; + + if (sysctl_sched_migration_cost == -1) + return 1; + if (sysctl_sched_migration_cost == 0) + return 0; + + delta = rq_clock_task(env->src_rq) - p->se.exec_start; + + return delta < (s64)sysctl_sched_migration_cost; +} +``` + +##15.6 WAKEUP_PREEMPTION +------- + + +在前面讲唤醒抢占的时候, 我们了解了 wakeup_preempt_entity 唤醒成功设置抢占标记的条件. +而 WAKEUP_PREEMPT 是唤醒抢占的开关, 如果不设置 WAKEUP_PREEMPTION, 那么将不进行唤醒抢占的检查. +那么唤醒将只会将 wakee 进程设置为 RUNNING, 并加入到就绪队列中. + + +```cpp +/* + * Preempt the current task with a newly woken task if needed: + */ +static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_flags) +{ + // ...... + /* + * Batch and idle tasks do not preempt non-idle tasks (their preemption + * is driven by the tick): + */ + if (unlikely(p->policy != SCHED_NORMAL) || !sched_feat(WAKEUP_PREEMPTION)) + return; + + find_matching_se(&se, &pse); + update_curr(cfs_rq_of(se)); + BUG_ON(!pse); + if (wakeup_preempt_entity(se, pse) == 1) { + /* + * Bias pick_next to pick the sched entity that is + * triggering this preemption. + */ + if (!next_buddy_marked) + set_next_buddy(pse); + goto preempt; + } + + return; + + // ...... +} +``` + + +##15.7 HRTICK +------- + + +##15.8 DOUBLE_TICK +------- + + +##15.9 LB_BIAS +------- + + +##15.10 NONTASK_CAPACITY +------- + +##15.11 TTWU_QUEU +------- + + +##15.12 SIS_AVG_CPU +------- + +##15.13 SIS_PROP +------- + +##15.14 WARN_DOUBLE_CLOCK +------- + +##15.15 RT_PUSH_IP +------- + +##15.16 RT_RUNTIME_SHARE +------- + +RT 线程的优先级是很高的, 如果 RT 线程一直运行, 则会把 COU 占满, 因此往往会通过 RT_BANDWIDTH 来限制 RT 的 CPU 使用率. + +调度器在检查一个调度实体运行时间是否超额时, 实际检查的是它所在的运行队列的 rt_rq[cpu]->rt_time 是否超过 rt_rq[cpu]->rt_runtime; + +但是 BANDWIDTH 都是一个整体的概念, 为了防止当前 CPU 上的线程负载很高被 throttled, 而其他核上 CPU 上线程负载却很低, 远没有 +到达要被 throttled 的水平线, 这样整体的 BANDWIDTH 其实没有超过限额. 因此一般调度器的 BANDWIDTH 都会实现一种 steal 机制或者 share +机制. 就是 BANDWIDTH 的时间片是大家共享的. 如果一个线程超出了限制, 而同一个 BANDWIDTH 的其他进程有空闲的 CPU 时间, +那么超出限额的进程可以尝试从空闲的 CPU 上窃取一部分运行时间. + +在 SMP系统中, 如果内核使能了 RT_RUNTIME_SHARE 特性, 如果运行队列的运行时间已经超额, 则会尝试去其他 CPU 上的 RT_RQ 队列中 +"借" 时间以扩张 rt_rq[cpu]->rt_runtime. + + +在 RT_BANDWIDTH 中定时器处理函数中, 如果发现当前 RQ 被 throttled 了. +则会调用 balance_runtime 窃取其他 RQ 的 CPU 时间. + +而 RT_RUNTIME_SHARE 就是 balance_runtime 的开关, 只有配置了 RT_RUNTIME_SHARE 才会做窃取. + +```cpp +//https://elixir.bootlin.com/linux/v4.14.14/source/kernel/sched/rt.c#L795 +static void balance_runtime(struct rt_rq *rt_rq) +{ + if (!sched_feat(RT_RUNTIME_SHARE)) + return; + + if (rt_rq->rt_time > rt_rq->rt_runtime) { + raw_spin_unlock(&rt_rq->rt_runtime_lock); + do_balance_runtime(rt_rq); + raw_spin_lock(&rt_rq->rt_runtime_lock); + } +} +``` # 参考资料 diff --git a/study/kernel/01-process/05-schedule/10-group/002-bandwidth/README.md b/study/kernel/01-process/05-schedule/10-group/002-bandwidth/README.md new file mode 100644 index 0000000..8cb15a6 --- /dev/null +++ b/study/kernel/01-process/05-schedule/10-group/002-bandwidth/README.md @@ -0,0 +1,37 @@ +--- + +title: 使用 Hexo 搭建 GitHub Page 博客(一) +date: 2018-09-02 18:40 +author: gatieme +tags: hexo +categories: + - hexo +thumbnail: +blogexcerpt: 博文摘要 + +--- + +| CSDN | GitHub | Hexo | +|:----:|:------:|:----:| +| [Aderstep--紫夜阑珊-青伶巷草](http://blog.csdn.net/gatieme) | [`AderXCoding/system/tools`](https://github.com/gatieme/AderXCoding/tree/master/system/tools) | [gatieme.github.io](https://gatieme.github.io) | + +
+ +知识共享许可协议 + +本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 + +因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦 + +
+ +http://www.wowotech.net/process_management/449.html +http://www.wowotech.net/process_management/451.html?utm_source=tuicool + +
+ +* 本作品/博文 ( [AderStep-紫夜阑珊-青伶巷草 Copyright ©2013-2017](http://blog.csdn.net/gatieme) ), 由 [成坚(gatieme)](http://blog.csdn.net/gatieme) 创作. + +* 采用知识共享许可协议知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) ( 包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的. + +* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问,请与我联系. diff --git a/study/kernel/10-bpf/01-mybcc/hello_world.py b/study/kernel/10-bpf/01-mybcc/hello_world.py index 28f79c9..4ef7cc8 100755 --- a/study/kernel/10-bpf/01-mybcc/hello_world.py +++ b/study/kernel/10-bpf/01-mybcc/hello_world.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# -*- coding: UTF-8 -*- # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") diff --git a/study/kernel/12-ftrace/00-use/README.md b/study/kernel/12-ftrace/00-use/README.md new file mode 100644 index 0000000..c4e7ca5 --- /dev/null +++ b/study/kernel/12-ftrace/00-use/README.md @@ -0,0 +1,36 @@ +--- + +title: 使用 ftrace(一) +date: 2018-09-02 18:40 +author: gatieme +tags: hexo +categories: + - hexo +thumbnail: +blogexcerpt: 博文摘要 + +--- + +| CSDN | GitHub | Hexo | +|:----:|:------:|:----:| +| [Aderstep--紫夜阑珊-青伶巷草](http://blog.csdn.net/gatieme) | [`AderXCoding/system/tools`](https://github.com/gatieme/AderXCoding/tree/master/system/tools) | [gatieme.github.io](https://gatieme.github.io) | + +
+ +知识共享许可协议 + +本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 + +因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦 + +
+ + + +
+ +* 本作品/博文 ( [AderStep-紫夜阑珊-青伶巷草 Copyright ©2013-2017](http://blog.csdn.net/gatieme) ), 由 [成坚(gatieme)](http://blog.csdn.net/gatieme) 创作. + +* 采用知识共享许可协议知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) ( 包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的. + +* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问,请与我联系. diff --git a/study/kernel/12-ftrace/README.md b/study/kernel/12-ftrace/README.md new file mode 100644 index 0000000..1de07f8 --- /dev/null +++ b/study/kernel/12-ftrace/README.md @@ -0,0 +1,35 @@ +--- + +title: 使用 Hexo 搭建 GitHub Page 博客(一) +date: 2018-09-02 18:40 +author: gatieme +tags: hexo +categories: + - hexo +thumbnail: +blogexcerpt: 博文摘要 + +--- + +| CSDN | GitHub | Hexo | +|:----:|:------:|:----:| +| [Aderstep--紫夜阑珊-青伶巷草](http://blog.csdn.net/gatieme) | [`AderXCoding/system/tools`](https://github.com/gatieme/AderXCoding/tree/master/system/tools) | [gatieme.github.io](https://gatieme.github.io) | + +
+ +知识共享许可协议 + +本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 + +因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦 + +
+ + +
+ +* 本作品/博文 ( [AderStep-紫夜阑珊-青伶巷草 Copyright ©2013-2017](http://blog.csdn.net/gatieme) ), 由 [成坚(gatieme)](http://blog.csdn.net/gatieme) 创作. + +* 采用知识共享许可协议知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) ( 包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的. + +* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问,请与我联系.