Приоритеты в Windows.

01.05.2019 Звуковые устройства

UID, EUID, GID, EGID

UID (User ID) - это идентификатор пользователя, создавшего данный процесс, точнее, копия значения UID родительского процесса. Менять атрибуты процесса могут только его создатель (владелец) и пользователь root.

UID представляет собой 32-битное целое число, но в целях совместимости рекомендуется, чтобы оно не превышало максимально 16-битного целого числа со знаком (32767).

EUID (Effective User ID) - это «эффективный», или текущий, пользовательский идентификатор процесса, предназначенный для того, чтобы определить, к каким ресурсам и файлам у процесса есть право доступа в данный момент. У большинства процессов значения UID и EUID одинаковы.

UID и EUID позволяют разграничить понятия персонификации и прав доступа. Значение EU1D можно устанавливать и сбрасывать, чтобы предоставлять процессу дополнительные полномочия или убирать их.

GID (Group ID) - это идентификатор группы, к которой принадлежит владелец процесса.

Эффективный (или текущий), идентификатор группы (Effective Group ID, EGID ) связан с атрибутом GID гак же, как значение EUID - с UID.

Порядок выполнения процессов определяется специальным системным процессом - планировщиком заданий .

Обычно в Linux-системах выполнение того ли иного процесса определяется приоритетом и обратной к нему величиной - фактором уступчивости.

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

Фактор уступчивости - это число, по которому ядро определяет свою политику в отношении процессов, конкурирующих за право доступа к центральному процессору. Чем выше фактор уступчивости, тем ниже приоритет процесса, и наоборот. Низкое или отрицательное значение означает использование высокого приоритета: процесс ведет себя не слишком уступчиво. Диапазон допустимых значений - от -20 до +19. По умолчанию равен 0.

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

Фактор уступчивости можно установить при создании процесса. Это делается с помощью команды nice. Команда renice позволяет изменять приоритет выполняемого процесса.

По определению, Windows является многозадачной операционной системой. То есть одновременно в ней могут выполняться несколько задач. Однако задача задаче рознь. И различие это заключается в приоритете. То есть, при выполнении какой-либо программы Windows распределяет ресурсы определенным образом, в зависимости от того, какой приоритет у какого процесса (программы). Программы в дальнейшем я буду называть процессами, так проще. Каждая запущенная программа в Windows представляет собой процесс. Приоритеты бывают разные - большие, маленькие, но об этом потом. Чем это может нам помочь? А вот чем. Многие сетуют на медленность выполнения программ на Vb. В свое время я на это наткнулся на самом наглядном примере. Представьте себе программу, которая должна через определенный интервал времени выполнять какое-либо действие - ну, например, что-то выводить пользователю. Просто - скажете Вы. Берем таймер и вперед. А если помимо этого периодически программа должна что-то еще считать, и не один раз, а таймеров много? Будет тормозить. Причем не Windows, а только программа. Несправедливо? Да. Это значит, что Windows отделяет мало ресурсов Вашей программе, которых ей явно недостаточно. Значит попросить у Windows больше, только как?

Вот так

Значит надо менять приоритет. Самое время о них поговорить. В Windows"98 приоритетов меньше, чем в Windows Me или 2000, но они таки есть J. Вот они.

Приоритет реального времени (real time) - программа выполняется так, как будто она одна и есть цель жизни Windows. Все ресурсы отдаются ей.

Высокий приоритет (high) - программа выполняется так, чтобы оставить чуть-чуть остальным приложениям.

Нормальный (normal) - выполнение идет обычным путем.

Низкий (idle) - если выполнение и идет, то только когда Windows делать нечего.

Ну так вот, запущенная программа сначала получает приоритет Normal, и выполняется своим чередом. При этом приоритете, что бы программа ни делала, она не сможет съесть ресурсов столько, чтобы повис Windows. В теории. Но нам так не подходит. Нам надо приоритет high или, если все очень напряжно, real time. Но real time - вещь опасная. Может запросто затормозиться даже мышка. А об остальных программах я и говорить на хочу. Просто копец и все тут. Итак, как же все таки приоритет поменять.

Снова API

Да, за установку приоритета отвечает функция SetPriorityClass. То есть, вызвав ее, и передав все, что ей надо, мы получим нужный приоритет.

Private Declare Function SetPriorityClass _ Lib "kernel32" (ByVal hProcess As Long, _ ByVal dwPriorityClass As Long) As Long

  • hProcess - это Handle процесса. О нем ниже.
  • dwPriorityClass - приоритет. Он то нам и нужен.

Константы приоритетов:

Private Const REALTIME_PRIORITY_CLASS = &H100 Private Const HIGH_PRIORITY_CLASS = &H80 Private Const NORMAL_PRIORITY_CLASS = &H20 Private Const IDLE_PRIORITY_CLASS = &H40

Все просто - берем константу и вперед, но нам надо получить Handle процесса. То есть, процесс и окно для Windows вещи хоть и почти синонимичные, но не всегда. Handle окна - одна вещь, Handle процесса - совсем другая. То есть, у процесса может быть много окон, но у окна только один процесс владелец. Значит, нам надо научиться находить Handle именно процесса. В этом нам поможет функция OpenProcess, которая после передачи ей параметров, скажет, что за Handle у процесса.

Private Declare Function OpenProcess _ Lib "kernel32" (ByVal dwDesiredAccess As Long, _ ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

dwDesiredAccess - что мы хотим узнать (Handle у процесса бывают разные, для завершения процесса - одни, для получения информации - другой). Мы будем использовать константу PROCESS_QUERY_INFORMATION, то есть опрашивать процесс.

Private Const PROCESS_QUERY_INFORMATION = &H400

bInheritHandle - переменная Boolean. Если ее передать True, то полученный Handle может в будущем быть использован другим процессом. Но нам это не надо. Передаем туда False.

DwProcessId - так, а это очередная вещь - идентификатор (id) процесса. Нам надо и его получить. Как? Просто! Функция GetCurrentProcessId, вызываемая без параметров (слава Богу) просто возвращает id текущего процесса.

Private Declare Function GetCurrentProcessId _ Lib "kernel32" Alias "GetCurrentProcessId" () As Long

Все. Можно вздохнуть и все сделать красиво.

Немного кода

Option Explicit Private Declare Function SetPriorityClass _ Lib "kernel32" (ByVal hProcess As Long, _ ByVal dwPriorityClass As Long) As Long Private Const REALTIME_PRIORITY_CLASS = &H100 Private Const HIGH_PRIORITY_CLASS = &H80 Private Const NORMAL_PRIORITY_CLASS = &H20 Private Const IDLE_PRIORITY_CLASS = &H40 Private Declare Function OpenProcess _ Lib "kernel32" (ByVal dwDesiredAccess As Long, _ ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long Private Const PROCESS_QUERY_INFORMATION = &H400 Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long Private Sub SetPriority(Priority As Long) Dim ProcId As Long "переменная для id процесса Dim ProcHandle As Long "переменная для handle процесса ProcId = GetCurrentProcessId "получим id ProcHandle = OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcId) "получили Handle Call SetPriorityClass(ProcHandle, Priority) " ставим приоритет End Sub Private Sub Form_Load() "ставим приоритет SetPriority HIGH_PRIORITY_CLASS End Sub

| Следующая страница

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

Вы должны понять, что приоритет - понятие относительное. Ведь в данный момент в очереди на выполнение могут стоят двадцать процессов, а в следующий - два. Поэтому приоритет - это «плавающее» значение, которое определяет сама система в зависимости от текущей ситуации.

В Linux значение приоритета может быть равно числу в диапазоне сорока значений. Как же я туманно выразился. На самом деле, все зависит от версии ядра Linux. Значение приоритета может быть в диапазоне от -20 до 19 или от 0 до 39. В обоих случаях возможное значение ограничено сорока числами. В ядрах версии 2.6.х значение приоритета находится в диапазоне от 0 до 39.

Чем меньше число – тем выше приоритет процесса. То есть процесс с приоритетом 5 имеет больший приоритет, чем процесс с приоритетом 16.

Вы не можете непосредственно изменять приоритет процесса, это прерогатива операционной системы. Но Вы можете определить, на сколько больше или меньше процесс будет «нравиться» системе. Для этого следует использовать поле nice. То есть для изменения приоритета администратор должен изменять значение поля nice. Если значение nice равно нулю - значит, у программы приоритет не изменен. Если в поле nice записано отрицательное число – приоритет процесса увеличен, положительное - уменьшен.

Давайте посмотрим на соответствующие поля, показанные программой :

$ ps -t pts/1 -o pid,pri,ni,comm PID PRI NI COMMAND 4205 24 0 bash 4246 24 0 ps $

Как видно из примера, у программ, выполняющихся на терминале pts/1, значение поля nice равно нулю. Следовательно, эти программы выполняются со стандартным приоритетом, установленным самой системой.

В следующем примере будут показаны программы с увеличенным приоритетом, которые в данный момент работают в системе (В качестве примера я хотел использовать программу ps «ps -e -o pid,pri,ni,comm», но почему-то значение поля приоритет выводилось неправильно. Нет в мире совершенства. Поэтому пришлось использовать top в командном режиме. )

$ top -b -n1 | grep "\-." | sed -e "1d" 3 root 10 -5 0 0 0 S 0.0 0.0 0:00.04 events/0 4 root 10 -5 0 0 0 S 0.0 0.0 0:00.01 khelper 5 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kthread 7 root 10 -5 0 0 0 S 0.0 0.0 0:00.16 kacpid 100 root 10 -5 0 0 0 S 0.0 0.0 0:00.07 kblockd/0 146 root 12 -5 0 0 0 S 0.0 0.0 0:00.00 aio/0 147 root 12 -5 0 0 0 S 0.0 0.0 0:00.00 xfslogd/0 148 root 12 -5 0 0 0 S 0.0 0.0 0:00.00 xfsdatad/0 871 root 12 -4 1472 456 384 S 0.0 0.2 0:00.02 udevd 1506 root 10 -5 0 0 0 S 0.0 0.0 0:00.07 ipw2100/0 $

Как видите, таких программ достаточно много.

Любой пользователь системы может изменить значение поля nice. Но существуют два ограничения:

  • Пользователь может изменить приоритет только у программ, выполняющихся с его правами.
  • Пользователь может только понизить приоритет (записать положительное число в поле nice).

Как обычно, суперпользователь может все! Он может изменить приоритет любому процессу системы, он может уменьшать и увеличивать приоритеты.

Для изменения приоритета можно воспользоваться программой top . Сначала получим список всех процессов выполняемых пользователем user1. Для краткости, заголовок top я буду удалять.

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME #C COMMAND 4316 user1 15 0 3332 1944 1192 S 0.0 0.8 0:00 0 bash 4326 user1 16 0 2064 1060 832 R 0.0 0.4 0:00 0 top

Для изменения приоритета процесса используйте команду r .

PID to renice: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME #C COMMAND 4326 user1 16 0 2064 1060 832 R 0.3 0.4 0:00 0 top 4316 user1 15 0 3332 1944 1192 S 0.0 0.8 0:00 0 bash

Программа попросит ввести PID процесса, которому следует изменить приоритет. Введите PID и нажмите Enter .

Renice PID 4326 to value: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME #C COMMAND 4326 user1 16 0 2064 1060 832 R 0.3 0.4 0:00 0 top 4316 user1 15 0 3332 1944 1192 S 0.0 0.8 0:00 0 bash

Теперь программа просит ввести значение, которое будет записано в поле nice. Введем число 10 и нажмем Enter .

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME #C COMMAND 4316 user1 15 0 3332 1944 1192 S 0.0 0.8 0:00 0 bash 4326 user1 26 10 2064 1060 832 R 0.0 0.4 0:00 0 top

Значение поля nice изменилось на 10. Соответственно изменилось и значение поля приоритета процесса.

Существуют еще две программы, которые можно использовать для изменения приоритета:

В большинстве версий UNIX используются уровни приоритета от 0 до 127. Будем для определенности считать, что 0 соответствует высшему приоритету, хотя в некоторых версиях дело обстоит наоборот.

Весь диапазон приоритетов разделяется на верхнюю часть (приоритеты режима ядра) и нижнюю часть (приоритеты режима задачи). Это деление показано на рис. 4‑3.

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

Базовое значение приоритета – это то значение, которое система по умолчанию присваивает новому процессу при его создании. Во многих версиях UNIX базовое значение равно высшему приоритету задачи + 20.

Относительный приоритет , который почему-то называется в UNIX «nice number », присваивается процессу при его создании. По умолчанию система устанавливает для процесса нулевое значение относительного приоритета. Обычный пользователь может только увеличить это значение (т.е. понизить приоритет процесса), а привилегированный пользователь может и уменьшить вплоть до высшего приоритета задачи (для самых приоритетных процессов). При создании нового процесса он наследует относительный приоритет родителя.

Штраф за использование процессорного времени увеличивается для работающего процесса с каждым прерыванием от таймера. Вследствие этого, высокоприоритетный процесс не сможет монополизировать использование процессора и время от времени должен будет уступать квант времени низкоприоритетным процессам. Однако система «не злопамятна»: через каждую секунду происходит уменьшение накопленных процессами штрафов наполовину. Таким образом, процесс, отлученный от процессора, через некоторое время восстановит свой исходный приоритет.

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

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

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

Давайте поговорим о приоритетах Windows процессов . В большинстве случаев «играться» с настройкой приоритетов нет необходимости, но, иногда, грамотный системный администратор может помочь системе более правильно распределить процессорное время между запущенными задачами. Единого рецепта нет, но путем «подбора и перебора» это вполне реализуемо. Где это может понадобиться? Например, в связке 1С-SQL можно дать больше процессорного времени 1С и SQL, как наиболее критичным к ресурсам процессам.

В общем случае, посмотреть и изменить приоритет запущенного процесса можно через Task Manager

Windows NT/2000/ 7 /2008

В Windows 2012 это “закопали» чуть глубже

Как видно из приведенных примеров, вам доступно всего 6 приоритетов (как выяснится позже, это классы приоритетов ). Достаточно? Microsoft считает, что да. Но давайте вспомним «легендарную» фразу Билла Гейста, который сказал, что «640 KB of RAM will be enough for everybody”. Но время показало, что это далеко не так. :)

А теперь давайте разберемся, как это есть на самом деле.

На самом деле в Windows существует 32 уровня приоритета, от 0 до 31.

Они группируются так:

  • 31 — 16 уровни реального времени;
  • 15 — 1 динамические уровни;
  • 0 — системный уровень, зарезервированный для потока обнуления страниц (zero-page thread).

При создании процесса, ему назначается один из шести классов приоритетов :

  1. Real time class (значение 24),
  2. High class (значение 13),
  3. Above normal class (значение 10),
  4. Normal class (значение 8),
  5. Below normal class (значение 6),
  6. или Idle class (значение 4).

Посмотреть приоритет процесса, как писалось выше, можно, используя Task Manager.

Примечание : Приоритеты Above normal и Below normal появились, начиная с Windows 2000.

Приоритет каждого потока (базовый приоритет потока ) складывается из приоритета его процесса и относительного приоритета самого потока. Есть семь относительных приоритетов потоков:

  1. Normal : такой же как и у процесса;
  2. Above normal : +1 к приоритету процесса;
  3. Below normal : -1;
  4. Highest : +2;
  5. Lowest : -2;
  6. Time critical : устанавливает базовый приоритет потока для Real time класса в 31, для остальных классов в 15.
  7. Idle : устанавливает базовый приоритет потока для Real time класса в 16, для остальных классов в 1.

В следующей таблице показаны приоритеты процесса, относительный и базовый приоритеты потока.

Приоритет потока Класс процесса Класс процесса
Idle class Below normal class Normal class Above normal class High class Real time class
1 Idle Idle Idle Idle Idle
2 Lowest
3 Below …
4 Idle class Normal Lowest
5 Above … Below …
6 Below normal class Highest Normal Lowest
7 Above … Below …
8 Normal class Highest Normal Lowest
9 Above … Below …
10 Above normal class Highest Normal
11 Above … Lowest
12 Highest Below …
13 High class Normal
14 Above …
15 Highest
15 Time critical Time critical Time critical Time critical Time critical
16 Idle
17
18
19
20
21
22 Lowest
23 Below …
24 Real time class Normal
25 Above …
26 Highest
27
28
29
30
31 Time critical

Теперь, когда мы все это узнали, что же с этим всем можно сделать? Ну, например, начать использовать.

Как еще можно запустить процесс с «нестандартным» приоритетом или изменить?

Метод 1. Запустить задачу/процесс и изменить приоритет через Task Manager.

Минусы метода:

  • Доступно только 6 приоритетов
  • Переключение приоритетов производится мышкой, не автоматизируется.

Метод 2. Можно воспользоваться командой START с соответствующими ключами

Доступные ключи, отвечающие за приоритеты, следующие (я умышленно опускаю ключи командной строки команды START не имеющие отношения к описываемому процессу работы с приоритетами):

C:\>start /?
Starts a separate window to run a specified program or command.
START ["title"]


LOW Start application in the IDLE priority class.
NORMAL Start application in the NORMAL priority class.
HIGH Start application in the HIGH priority class.
REALTIME Start application in the REALTIME priority class.
ABOVENORMAL Start application in the ABOVENORMAL priority class.
BELOWNORMAL Start application in the BELOWNORMAL priority class.

Как видим, команда START дает возможность запустить процесс все с теми же 6-ю приоритетами, которые доступны через Task Manager

Минус метода:

  • Доступно только 6 приоритетов

Метод 3. Использование утилиты wmic.exe

Как было показано выше, Task Manager, и команда START достаточно неуклюжи для задачи назначения приоритетов. Посмотрим, как это применять более гибко. Будем использовать утилиту wmic.exe .

Командная строка:

wmic process where name="AppName" CALL setpriority ProcessIDLevel

wmic process where name="calc.exe" CALL setpriority 32768

wmic process where name="calc.exe" CALL setpriority "above normal"

Приоритеты (предопределенные):

  • idle: 64
  • below normal: 16384
  • normal: 32
  • above normal: 32768
  • high priority: 128
  • real time: 256

Отступление . Что делать если существует несколько одноименных процессов? Приоритет процесса можно менять как по имени процесса, так и с использованием PID (Process ID) процесса.

Вот короткий пример запуска wmic.exe для получения необходимой информации

Используем команду:

Примечание : пример выполнения этой команды приводить не буду. Слишком большой список процессов получается. Сделаете это самостоятельно, при желании.

Вы получите список процессов, запущенных на вашем локальном компьютере. Теперь выполните команду:

wmic process list brief | find "cmd.exe"

Результат:

Специально запустил несколько копий cmd.exe, чтобы иллюстрация была более полной.

Теперь список процессов ограничен только теми процессами, в имени исполняемого модуля которых присутствует строка «cmd.exe». Обратите внимание на PID процесса(ов).

Теперь давайте попробуем отобрать интересующие нас процессы, используя непосредственно WMI и не прибегая к стандартным средствам командной строки. Для этого просто напишите:

wmic process where description="cmd.exe" list brief

Результат:

Сравните полученные результаты. Запомните PID процесса CMD.EXE.

Командная строка для запуска wmic.exe

wmic process where processid="XXXX" CALL setpriority ProcessIDLevel

Ну а теперь можем изменить приоритет конкретного процесса (например с PID=8476):

wmic process where processid="8476" CALL setpriority 32768

wmic process where processid="8476" CALL setpriority "above normal"