Планирование группы Linux для пользователя не применяется к процессу с установленным идентификатором

В ядре Linux 2.6.28-11 я использую setpriority для смещения количества процессорного времени, получаемого различными пользовательскими процессами. Пользователь 1 должен получить удвоенную мощность ЦП пользователя 2. Используя setpriority Linux, я назначил пользователю 2 более низкий приоритет (более высокий с точки зрения приятных значений). Когда я запускаю ту же самую программу через оболочку с загруженным компьютером, выполнение пользователя 2 занимает в два раза больше времени, чем выполнение пользователя 1. Однако, если я запускаю программу от имени пользователя root, а затем использую setuid, seteuid, setgid, setegid и setgroups, чтобы стать пользователем 2 (еще раз компьютер находится под нагрузкой, и точно такая же программа запускается пользователем 1 таким же образом) , программы выполняются одинаковое количество времени; Процесс пользователя 2 планировался не меньше, чем процесс пользователя 1. Как я могу обойти это? Нужно ли мне устанавливать что-то еще, чтобы планировщик понял, что процесс теперь является частью другого пользователя?

Запускаемая программа написана на Python.


person BrainCore    schedule 17.12.2009    source источник


Ответы (1)


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

/* C */
#include <sys/resource.h>
int proc_prio = getpriority(PRIO_PROCESS, getpid()),
    pgrp_prio = getpriority(PRIO_PGRP, getpgrp()),
    user_prio = getpriority(PRIO_USER, getuid());
setpriority(PRIO_PROCESS, getpid(),
    proc_prio < pgrp_prio ? pgrp_prio < user_prio ? user_prio
                                                  : pgrp_prio
                          : proc_prio < user_prio ? user_prio
                                                  : proc_prio);

# Python
import ctypes
import os
PRIO_PROCESS, PRIO_PGRP, PRIO_USER = 0, 1, 2
libc = ctypes.CDLL('libc.so.6')
libc.setpriority(PRIO_PROCESS, os.getpid(),
    max(libc.getpriority(PRIO_PROCESS, os.getpid()),
        libc.getpriority(PRIO_PGRP, os.getpgrp()),
        libc.getpriority(PRIO_USER, os.getuid())))

Или, конечно, вы можете установить приоритет другого процесса с соответствующими привилегиями.

person ephemient    schedule 17.12.2009
comment
Благодарю за разъяснение. Есть ли у вас хороший материал для чтения, в котором рассказывается, как Linux обрабатывает приоритеты и расставляет их по приоритетам? Учитывая приведенное выше решение, которое действительно работает, кажется, что невозможно гарантировать, что все процессы пользователя 1 используют только x% процессора, если у них есть какие-либо процессы, исходящие из разветвленного корневого процесса, который был setuid- изд. Это правда? - person BrainCore; 18.12.2009
comment
у меня нет хороших материалов для чтения, но setuid проверяет только то, являюсь ли я пользователем root* и имеет ли целевой UID менее RLIMIT_NPROC процессов?. Другие лимиты ресурсов и приоритет не проверяются и не трогаются. * (на самом деле проверка не запрещена LSM, есть ли у меня CAP_SETUID, и если я действительно меняю реальный UID, имеет ли цель меньше процессов, чем RLIMIT_NPROC, или указанный UID равен текущему реальному UID или сохраненному UID?) - person ephemient; 18.12.2009
comment
В какой-то степени вы можете посмотреть коннектор netlink для событий PROC_EVENT_UID, чтобы применить эти исправления, но я думаю, что вам действительно нужны процессорные наборы на основе UID и планирование на основе cgroup. - person ephemient; 18.12.2009
comment
Я уже реализовал желаемую систему, используя коннектор событий процесса через netlink, как вы предложили. Когда я обнаружил, что в CFS (Completely Fair Scheduler) существует надежное планирование групп пользователей, я решил, что это заслуживает дальнейшего изучения. Я обязательно ознакомлюсь с планированием на основе cgroup. Спасибо еще раз. - person BrainCore; 18.12.2009