Плагскхед: горячее обновление подсистемы планировщика ядра Linux
Плагскхед — это набор средств разработки (SDK), который позволяет динамически заменять подсистему планировщика без перезагрузки системы или приложений. Это позволяет сократить время простоя до миллисекунд. Плагскхед позволяет динамически изменять, добавлять и удалять функции планировщика в производственной среде, чтобы удовлетворить потребности различных сценариев использования и поддерживает откат изменений.
Мотивация
Как это работает Планировщик не является отдельным модулем в ядре, а интегрирован в него. Плагскхед использует концепцию модульности: он предоставляет инструмент для определения границ планировщика и извлекает планировщик из исходного кода ядра в отдельный каталог. Разработчики могут вносить изменения в извлечённый код планировщика, компилировать его в новый модуль ядра планировщика и динамически заменять старый планировщик в ядре.
Для функций плагскхед предоставляет внешние интерфейсы. Заменяя эти функции в ядре, ядро может обойти существующую логику выполнения и выполнить новый модуль планировщика, тем самым обновляя функцию. Функции в модуле либо являются интерфейсными функциями, либо внутренними функциями; все остальные функции считаются внешними функциями.
Что касается данных, плагскхед разделяет данные на частные и общие. Частные данные распределяются по модулю независимо, в то время как общие данные совместно используются модулем и ядром. Глобальные переменные можно преобразовать в частные данные путём переопределения или в общие данные путём объявления. По умолчанию статические глобальные переменные помечаются как частные данные, а нестатические глобальные переменные — как общие данные. Однако для улучшения работы системы некоторые глобальные переменные настраиваются вручную в файле конфигурации границ.
В процессе горячего обновления синхронизация состояния данных является ключевой проблемой. Данные делятся на основные и неосновные в зависимости от необходимости восстановления состояния. Основные данные включают rq, cfs_rq, rt_rq, dl_rq, cfs_bandwidth, sched_class, sysfs, debugfs, sched_features и timer. Остальные данные считаются неосновными данными, включая sched_domain_topology, task_group_cache и связанные с планировщиком sysctls, tracepoint и cpumask. Плагскхед восстанавливает состояние основных данных планировщика с помощью технологии sched rebuild. Для неосновных данных частные данные не требуют синхронизации состояния, а общие данные автоматически наследуют состояние без дополнительной обработки. Этот универсальный подход к восстановлению состояния эффективно решает проблему синхронизации состояния.
Основные данные | Неосновные данные | |
---|---|---|
Частное | Восстановление | Переинициализация |
Общее | Восстановление | Наследование |
Важно отметить, что структура и семантика членов структуры не должны изменяться произвольно. Если необходимо добавить новых членов, рекомендуется использовать зарезервированные поля, предварительно определённые в структуре.
Извлечение границ Поскольку планировщик сам по себе не является модулем, необходимо чётко определить его границы, чтобы сделать его модульным. Инструмент определения границ использует информацию, собранную во время компиляции ядра, такую как имена символов, местоположения, атрибуты символов и отношения вызовов функций, для извлечения кода планировщика из исходного кода ядра. Процесс извлечения включает сбор информации, анализ границ на основе файла конфигурации границ и извлечение кода внутри границ в отдельный каталог kernel/sched/mod.
Разработка планировщика После извлечения код модуля планировщика помещается в отдельный каталог, где разработчики могут модифицировать код для настройки планировщика под конкретные сценарии. Важно учитывать ограничения, описанные в разделе «Ограничения».
Компиляция и установка планировщика По завершении разработки код модуля планировщика вместе с программами для загрузки/выгрузки и другими связанными функциями компилируется в модуль ядра и создаётся пакет RPM для планировщика. После установки новый планировщик заменяет старый в ядре. Процесс установки включает в себя:
Сценарии использования
Быстрый старт На данный момент плагскхед поддерживает систему Anolis OS 8.6 ANCK. Для других систем требуется настройка файла конфигурации границ. Чтобы упростить настройку среды разработки, предоставляются образы контейнеров и Dockerfile, избавляя разработчиков от необходимости самостоятельно создавать среду разработки. Для демонстрации процесса обновления используется экземпляр ECS (64CPU + 128GB) с установленной системой Anolis OS 8.6 ANCK, на котором будет выполнено горячее обновление планировщика ядра.
Процесс быстрого старта включает следующие шаги:
# yum install anolis-repos -y
# yum install yum-utils podman kernel-debuginfo-$(uname -r) kernel-devel-$(uname -r) --enablerepo=Plus-debuginfo --enablerepo=Plus -y
# mkdir /tmp/work && cd /tmp/work
# yumdownloader --source kernel-$(uname -r) --enablerepo=Plus
# podman run -itd --name=plugsched -v /tmp/work:/tmp/work -v /usr/src/kernels:/usr/src/kernels -v /usr/lib/debug/lib/modules:/usr/lib/debug/lib/modules plugsched-registry.cn-hangzhou.cr.aliyuncs.com/plugsched/plugsched-sdk
# podman exec -it plugsched bash
# cd /tmp/work
# uname_r=$(uname -r)
# plugsched-cli extract_src kernel-${uname_r%.*}.src.rpm ./kernel
# plugsched-cli init $(uname -r) ./kernel ./scheduler
diff --git a/scheduler/kernel/sched/mod/core.c b/scheduler/kernel/sched/mod/core.c
index 9f16b72..21262fd 100644
--- a/scheduler/kernel/sched/mod/core.c
+++ **b/scheduler/kernel/sched/mod/core.c**
static void __sched notrace __schedule(bool preempt) { struct rq *rq; int cpu;
if (sched_feat(PLUGSCHED_TEST)) {
printk_once("I am the new scheduler: __schedule\n");
}
cpu = smp_processor_id();
rq = cpu_rq(cpu);
prev = rq->curr;
}
**diff --git a/scheduler/kernel/sched/mod/features.h b/scheduler/kernel/sched/mod/features.h**
SCHED_FEAT(PLUGSCHED_TEST, false)
7. Чтобы собрать сгенерированный пакет RPM, скопируйте его на хост и выйдите из контейнера. Затем проверьте текущие параметры sched_features:
```shell
# uname_r=$(uname -r)
# cp /tmp/work/scheduler/working/rpmbuild/RPMS/x86_64/scheduler-xxx-${uname_r%.*}.yyy.x86_64.rpm /tmp/work/scheduler-xxx.rpm
# exit
exit
# cat /sys/kernel/debug/sched_features
GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
# rpm -ivh /tmp/work/scheduler-xxx.rpm
# lsmod | grep scheduler
scheduler 503808 1
# dmesg | tail -n 10
[ 2186.213916] cni-podman0: port 1(vethfe1a04fa) entered forwarding state
[ 6092.916180] Hi, scheduler mod is installing!
[ 6092.923037] scheduler: total initialization time is 6855921 ns
[ 6092.923038] scheduler module is loading
[ 6092.924136] scheduler load: current cpu number is 64
[ 6092.924137] scheduler load: current thread number is 667
[ 6092.924138] scheduler load: stop machine time is 249471 ns
[ 6092.924138] scheduler load: stop handler time is 160616 ns
[ 6092.924138] scheduler load: stack check time is 85916 ns
[ 6092.924139] scheduler load: all the time is 1097321 ns
# cat /sys/kernel/debug/sched_features
NO_PLUGSCHED_TEST GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
# echo PLUGSCHED_TEST > /sys/kernel/debug/sched_features
# dmesg | tail -n 5
[ 6092.924138] scheduler load: stop machine time is 249471 ns
[ 6092.924138] scheduler load: stop handler time is 160616 ns
[ 6092.924138] scheduler load: stack check time is 85916 ns
[ 6092.924139] scheduler load: all the time is 1097321 ns
[ 6512.539300] I am the new scheduler: __schedule
# rpm -e scheduler-xxx
# dmesg | tail -n 8
[ 6717.794923] scheduler module is unloading
[ 6717.809110] scheduler unload: current cpu number is 64
[ 6717.809111] scheduler unload: current thread number is 670
[ 6717.809112] scheduler unload: stop machine time is 321757 ns
[ 6717.809112] scheduler unload: stop handler time is 142844 ns
[ 6717.809113] scheduler unload: stack check time is 74938 ns
[ 6717.809113] scheduler unload: all the time is 14185493 ns
[ 6717.810189] Bye, scheduler mod has be removed!
#
# cat /sys/kernel/debug/sched_features
GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE
``` **НОТ_СИС_СРУ CPU СИС_ПРОП НОТ_ВАРН_ДАБЛ_КЛОК РТ_ПУШ_ИПИ РТ_РУНТЙМ_ШАРЕ НОТ_ЛБ_МИН АТТАЧ_ЭЙДЖ_ЛОАД ВА_АЙДЛЕ ВА_ВЕЙТ ВА_БИАС НОТ_ВА_СТАТИК_ВЕЙТ УТЙЛ_ЕСТ ИД_АЙДЛЕ_СРУ ИД_РЕСКЮ_ЭКСПЛЕ НОТ_ИД_ЭКСПЛЕ_НЕВЕР_ХОТ НОТ_ИД_ЛУЗ_ЭКСПЛЕ ИД_ЛАСТ_ХАЙКЛАСС_СТЕЙ**
Внимание: нельзя использовать команду «rmmod» для непосредственного удаления модуля планировщика, следует использовать стандартные команды «rpm или yum» для удаления пакета планировщика.
Q: Что содержится в модуле планировщика после разделения границ по умолчанию?
Содержит следующее:
Q: Какие функции можно изменить при горячей замене планировщика?
После завершения извлечения границ в каталоге kernel/sched/mod файлы определяют функции, которые можно изменять. Например, в примере быстрого запуска диапазон функций, которые могут быть изменены в модуле планировщика, включает более 1 тыс. функций. Однако есть некоторые моменты, на которые следует обратить внимание, см. раздел «Ограничения».**
В: Можно ли изменить границы модуля планировщика?
Можно изменить, изменив файл конфигурации границ, чтобы изменить границы планировщика. Например, путём изменения файлов кода, интерфейсов и т. д., см. здесь. Обратите внимание, что если границы планировщика были изменены, перед выпуском необходимо провести тщательное тестирование.
Q: Поддерживает ли plugsched какие-либо версии ядра Linux?
Теоретически plugsched не зависит от версии ядра, мы протестировали версии 3.10 и 4.19, другие версии требуют самостоятельной адаптации и тестирования разработчиками.
Q: Можно ли изменять функции в заголовочных файлах?
Можно. Мы провели разделение границ для функций в заголовочном файле, и функции, помеченные как «DON'T MODIFY INLINE EXTERNAL FUNCTION», в заголовочном файле каталога kernel/sced/mod не могут быть изменены, а остальные функции могут быть изменены.
Q: Можно ли модифицировать структуры данных?
Нельзя произвольно изменять размер структуры данных и семантику членов, но можно изменять зарезервированные поля в структуре данных.
Q: Будет ли снижение производительности после замены внутреннего планировщика?
Накладные расходы самого планировщика невелики и ими можно пренебречь. Кроме того, это также зависит от модификации планировщика разработчиком. После теста производительности, если нет никаких изменений, то влияния на производительность нет.
Q: Сколько времени занимает загрузка модуля? Насколько долго?
Это зависит от текущей нагрузки системы и количества процессов, чем больше процессов и чем выше нагрузка, тем дольше время простоя. В нашем тесте на 104-ядерном процессоре с более чем 10 тыс. процессов время простоя не превышает 10 мс.
Q: В чём разница между этим и kpatch? Является ли это оптимизацией kpatch?
kpatch — это оптимизация с уровнем детализации функций, plugsched — это оптимизация на уровне подсистемы, некоторые функции и реализации невозможно оптимизировать с помощью kpatch, например, kpatch не может изменить функцию __schedule и не может одновременно изменить более тысячи функций.
Q: Есть ли конфликт с kpatch? Это оптимизация kpatch?
Есть конфликт, если области модификации kpatch и plugsched пересекаются, перекрывающаяся часть будет покрыта plugsched. Тем не менее, мы разработали механизм обнаружения конфликтов, который можно использовать в производственной среде.
Q: Можно ли изменять функции вне границ планировщика?
Можно, мы предоставляем механизм sidecar, который позволяет одновременно изменять функции за пределами границ планировщика. Например, некоторые исправления исправляют планировщик и содержимое cpuacct, и вы можете использовать механизм sidecar для обновления содержимого cpuacct.
plugsched — это SDK для горячего подключения планировщика ядра Linux, разработанный Alibaba и лицензированный по лицензии GPLv2+ или лицензии BSD-3-Clause. Этот продукт содержит различные сторонние компоненты под другими лицензиями с открытым исходным кодом. Дополнительную информацию см. в файле NOTICE.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )