Автоматическая настройка приоритетов процессов под Linux

Я пытаюсь написать программу, которая автоматически устанавливает приоритеты процесса на основе файла конфигурации (в основном пары путь - приоритет).

Я думал, что лучшим решением будет модуль ядра, который заменяет системный вызов execve (). Жаль, что таблица системных вызовов не экспортируется в версии ядра > 2.6.0, поэтому невозможно заменить системные вызовы без действительно уродливые хаки.

Я не хочу сделать следующий:

-замените двоичные файлы сценариями оболочки, которые запускают и изменяют двоичные файлы. - Исправление / перекомпиляция ядра Ubuntu - Уродливые хаки, такие как чтение исполняемой памяти ядра и угадывание местоположения таблицы syscall - Опрос запущенных процессов

Я действительно хотите быть:

- возможность управления приоритетом любого процесса на основе исполняемого пути и файла конфигурации. Правила применяются к любому пользователю.

кто-нибудь из вас есть идеи, как выполнить эту задачу?

7 ответов


Если вы остановились на решении опроса, большинство функций, которые вы хотите реализовать, уже существуют в Автоматический Хороший Демон. Вы можете настроить хорошие уровни для процессов на основе имени процесса, пользователя и группы. Даже можно динамически настраивать приоритеты процессов на основе того, сколько времени процессора он использовал до сих пор.


иногда опрос является необходимостью, и даже больше оптимальный в конце концов -- верьте или нет. Это зависит от множества переменных.

Если затраты на опрос достаточно низки, это намного превышает дополнительную сложность, стоимость и риск разработки собственных крючков ядра стиля, чтобы получить уведомление об изменениях, которые вам нужны. Что сказал:, когда крючки или события уведомления доступны или могут быть легко введены, они, безусловно, должны использоваться, если ситуация звонки.

Это классический программист "совершенства". Как инженеры, мы стремимся к совершенству. Но это реальный мир и иногда компромиссы должны быть сделаны. По иронии судьбы, более совершенное решение может быть менее эффективным в некоторых случаях.

Я разрабатываю аналогичный "процесс и процесс приоритет оптимизации автоматизации" инструмент для Windows под названием Process Lasso (не реклама, его бесплатно). У меня был аналогичный выбор, чтобы сделать и иметь гибридное решение на месте. Крючки режима ядра доступны для определенных событий, связанных с процессом в Windows (создание и уничтожение), но они не только не отображаются в пользовательском режиме, но и не полезны при мониторинге других метрик процесса. Я не думаю, что какая-либо ОС будет изначально информировать Вас о любых изменениях в любой метрике процесса. Накладные расходы для этого множества различных крючков могут быть намного больше, чем простой опрос.

наконец, учитывая высокую частоту изменений, она может быть лучше обрабатывать все изменения сразу (опрос с интервалом) против событий/крючков уведомлений, которые, возможно, придется обрабатывать еще много раз в секунду.

вы правы, чтобы держаться подальше от сценариев. Почему? Потому что они медленные (э-э). Конечно, планировщик linux делает довольно хорошую работу по обработке связанных потоков CPU, понижая их приоритет и вознаграждая (обновляя) приоритет связанных потоков ввода-вывода-так что даже при высоких нагрузках скрипт должны быть отзывчивым, я думаю.


конечно, просто повторите /proc/nnn/exe, чтобы получить путь запущенного изображения. Используйте только те слеши, остальные ядра проков.

Проверьте, обработали ли вы его, в противном случае найдите новый приоритет в файле конфигурации и используйте renice(8) для настройки его приоритета.


есть еще одна точка атаки, которую вы можете рассмотреть: замените систему динамический компоновщик с измененным, который применяет вашу логику. (См. статьи для некоторых хороших примеров того, что можно в значительной степени пренебречь искусства линкера взлома).

где такой подход будет иметь проблемы с чисто статически файлы. Я сомневаюсь, что есть много в современной системе, которая на самом деле не связывает что-то динамически (например, busybox-static будучи очевидными исключениями, хотя вы можете рассматривать возможность получить минимальную оболочку вне ваших элементов управления как функцию, когда все идет ужасно неправильно), так что это не может быть большим делом. С другой стороны, если политики приоритетов предназначены для наведения порядка в перегруженной общей многопользовательской системе, вы можете увидеть, как умные пользователи готовят статические связанные версии приложений, чтобы избежать приоритетов компоновщика.


Если вы хотите сделать это как модуль ядра, вы можете посмотреть, как сделать свой собственный двоичный загрузчик. Примеры см. В следующих исходных файлах ядра:

$KERNEL_SOURCE/fs/binfmt_elf.c
$KERNEL_SOURCE/fs/binfmt_misc.c
$KERNEL_SOURCE/fs/binfmt_script.c

они могут дать вам первое представление о том, с чего начать.

вы можете просто изменить загрузчик ELF, чтобы проверить наличие дополнительного раздела В файлах ELF и при обнаружении использовать его содержимое для изменения приоритетов планирования. Тогда вам даже не нужно будет управлять отдельными файлами конфигурации, а просто добавить новый раздел для каждого исполняемого файла ELF вы хотите управлять этим способом, и вы сделали. См. objcopy / objdump инструментов binutils для добавления новых разделов в файлы ELF.


у кого-нибудь из вас есть идеи о том, как выполнить эту задачу?

Как идея рассмотрите возможность использования в AppArmor в режиме жалобы. Это будет регистрировать определенные сообщения в syslog, которые вы можете слушать.


если рассматриваемые процессы запускаются путем выполнения исполняемого файла с известным путем, вы можете использовать inotify механизм для наблюдения за событиями в этом файле. Выполнение его вызовет I_OPEN и I_ACCESS событие.

к сожалению, это не скажет вам, какой процесс вызвал событие, но вы можете проверить, какой /proc/*/exe являются символической ссылкой на исполняемый файл в вопросе и renice идентификатор процесса в вопрос.

Е. Г. вот это реализация сырой в Perl, используя Linux:: Inotify2 (который, на Ubuntu, предоставляется liblinux-inotify2-perl пакета):

perl -MLinux::Inotify2 -e '
  use warnings;
  use strict;
  my $x = shift(@ARGV);
  my $w = new Linux::Inotify2;
  $w->watch($x, IN_ACCESS, sub
  {
    for (glob("/proc/*/exe"))
    {
      if (-r $_ && readlink($_) eq $x && m#^/proc/(\d+)/#)
      {
        system(@ARGV, )
      }
    }
  });
  1 while $w->poll
' /bin/ls renice

вы можете, конечно, сохранить код Perl в файл, скажем onexecuting вставьте первой строкой #!/usr/bin/env perl, сделайте файл исполняемым, поместите его на свой $PATH и дальше использовать onexecuting /bin/ls renice.

затем вы можете использовать эту утилиту в качестве основы для реализации различных политик для изменения исполняемых файлов. (или делать другие вещи.)