SetPriorityClass эквивалент в Linux - PullRequest
3 голосов
/ 17 апреля 2011

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

SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN);

// initialization tasks

SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END);

// daemon is ready and running at normal priority

AFAIK, в Unices я могу назвать nice или setpriority и снизить приоритет процесса, но не могу поднять его до того, что былопри создании процесса (т.е. нет эквивалента второму вызову SetPriorityClass), если у меня нет привилегий суперпользователя.Есть ли случайно другой способ сделать это, что я скучаю?(Я знаю, что могу создать поток инициализации, который работает с низким приоритетом, и ждать его завершения в основном потоке, но я бы предпочел избегать его)

edit: бонусные баллы за эквивалент SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);и SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);

Ответы [ 3 ]

5 голосов
/ 20 апреля 2011

Вы сказали, что ваша обработка требует много памяти, поэтому решения, использующие nice, не будут работать.nice обрабатывает приоритет доступа ЦП, а не доступа ввода-вывода.PROCESS_MODE_BACKGROUND_BEGIN снижает приоритет ввода-вывода, а также приоритет процессора и требует наличия функций ядра, которых нет в XP и более ранних версиях.

Управление приоритетом ввода / вывода не переносимо в Unices, но есть решение для современных ядер Linux.Вам нужно будет CAP_SYS_ADMIN, чтобы снизить приоритет ввода / вывода до IO_PRIO_CLASS_IDLE, но без этого можно снизить и повысить приоритет в классе наилучших усилий.

Вызов ключевой функции: ioprio_set, который вам придется вызывать через оболочку syscall:

static int ioprio_set(int which, int who, int ioprio)
{
    return syscall(SYS_ioprio_set, which, who, ioprio);
}

Для полного примера источника, см. Здесь .

В зависимости от разрешений ваш вход в фоновый режим может быть либо IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_IDLE,0), либо IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_BE,7).Последовательность должна быть такой:

#define IOPRIO_PRIO_VALUE(class, data)  (((class) << IOPRIO_CLASS_SHIFT) | data)

ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_BE,7));
// Do work
ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IO_PRIO_CLASS_BE,4));

Обратите внимание, что многие из вас не имеют разрешения вернуться к своему первоначальному приоритету io, поэтому вам нужно будет вернуться к другому значению наилучшего усилия.

3 голосов
/ 19 апреля 2011

На самом деле, если у вас достаточно свежее ядро ​​ Linux , возможно, есть решение. Вот что говорит TLPI:

В ядрах Linux до 2.6.12 непривилегированный процесс может использовать setpriority () только для (необратимо) понизить свой или другой процесс хорошее значение.

Начиная с ядра 2.6.12, Linux предоставляет предел ресурса RLIMIT_NICE, который разрешает непривилегированные процессы увеличить хорошие значения. Непривилегированный Процесс может повысить свою собственную ценность до максимума, указанного формула 20 - rlim_cur, где rlim_cur текущий софт RLIMIT_NICE ограничение ресурса.

Так что в основном вы должны:

  1. Используйте ulimit -e для установки RLIMIT_NICE
  2. Используйте setpriority как обычно

Вот пример

Редактировать /etc/security/limits.conf. Добавить

cnicutar    -    nice    -10

Проверьте с помощью ulimit

cnicutar@aiur:~$ ulimit -e
30

Нам нравится этот предел, поэтому мы не меняем его.

приятно Ls

cnicutar@aiur:~$ nice -n -10 ls tmp
cnicutar@aiur:~$ 

cnicutar@aiur:~$ nice -n -11 ls tmp
nice: cannot set niceness: Permission denied

setpriority пример

#include <stdio.h>
#include <sys/resource.h>
#include <unistd.h>

int main()
{
        int rc;

        printf("We are being nice!\n");
        /* set our nice to 10 */
        rc = setpriority(PRIO_PROCESS, 0, 10);
        if (0 != rc) {
                perror("setpriority");
        }

        sleep(1);

        printf("Stop being nice\n");
        /* set our nice to -10 */
        rc = setpriority(PRIO_PROCESS, 0, -10);
        if (0 != rc) {
                perror("setpriority");
        }

        return 0;
}

Тестовая программа

cnicutar@aiur:~$ ./nnice 
We are being nice!
Stop being nice
cnicutar@aiur:~$ 

Единственный недостаток - это то, что он не переносим на другие Unix-ы (или это Unices ?).

0 голосов
/ 19 апреля 2011

Чтобы снизить приоритет и затем вернуть его обратно, вы можете:

  1. вилка ()
  2. РЕБЕНОК: понизить приоритет
  3. РОДИТЕЛЬ: ждать ребенка (сохраняя приоритет родителя)
  4. РЕБЕНОК: делать работу (с более низким приоритетом)
  5. PARENT: продолжить с первоначальным приоритетом после завершения дочернего процесса.

Это должно быть UNIX-переносимое решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...