Во многих других UNIX-системах тоже имеются интерфейсы для управления привязкой к процессорам. Например, HP-UX и Solaris предоставляют системный вызов pset_bind().

Системный вызов sched_setaffinity() привязывает к ЦПУ процесс, заданный с помощью аргумента pid. Если pid равен 0, изменения будут применены к вызывающему процессу.

#define _GNU_SOURCE

#include

int sched_setaffinity(pid_t pid, size_t len, cpu_set_t *set);

Возвращает 0 при успешном завершении или –1, если произошла ошибка

ЦПУ, который будет привязан к процессу, описывается с помощью структуры cpu_set_t, на которую указывает аргумент set.

Привязка к процессору на самом деле выполняется на уровне отдельных потоков и может быть изменена отдельно для каждого потока в группе. Если нам нужно изменить привязку для определенного потока, мы можем указать для аргумента pid значение, которое возвращает вызов gettid(). Если аргумент pid равен 0, берется вызывающий поток.

Тип данных cpu_set_t реализован в виде битовой маски, однако обращаться с ним следует как с непрозрачной структурой. Все изменения в содержимое этой структуры нужно выполнять с помощью макросов CPU_ZERO(), CPU_SET(), CPU_CLR() и CPU_ISSET().

#define _GNU_SOURCE

#include

void CPU_ZERO(cpu_set_t *set);

void CPU_SET(int cpu, cpu_set_t *set);

void CPU_CLR(int cpu, cpu_set_t *set);

int CPU_ISSET(int cpu, cpu_set_t *set);

Возвращает истину (1), если cpu входит в set, и ложь (0), если это не так

Эти макросы вносят такие изменения в набор процессоров, на который указывает set:

• CPU_ZERO() инициализирует набор set, делая его пустым;

• CPU_SET() добавляет процессор cpu в набор set;

• CPU_CLR() удаляет процессор cpu из набора set;

• CPU_ISSET() возвращает 1, если процессор cpu входит в набор set.

Библиотека GNU C также предоставляет целый ряд других макросов для работы с наборами процессоров. Подробности ищите на справочной странице CPU_SET(3).

Процессоры в наборе пронумерованы, начиная с нуля. В заголовочном файле находится объявление константы CPU_SETSIZE, значение которой на один больше, чем количество процессоров, которое можно уместить в переменной cpu_set_t (1024).

Аргумент len, который передается вызову sched_setaffinity(), обозначает число байтов в аргументе set (то есть sizeof(cpu_set_t)).

Следующий код позволяет процессу, указанному с помощью аргумента pid, выполняться четырехпроцессорной системе на любом ЦПУ, кроме первого:

cpu_set_t set;

CPU_ZERO(&set);

CPU_SET(1, &set);

CPU_SET(2, &set);

CPU_SET(3, &set);

sched_setaffinity(pid, CPU_SETSIZE, &set);

Если процессоры, указанные в аргументе set, не соответствуют ни одному ЦПУ в системе, вызов sched_setaffinity() завершается ошибкой EINVAL.

Если в наборе не указан ЦПУ, на котором процесс выполняется в текущий момент, процесс мигрирует на один из ЦПУ из заданного набора.

Непривилегированный процесс может привязать другую программу к определенному ЦПУ только в том случае, только если его действующий пользовательский идентификатор совпадает с действующим или реальным пользовательским идентификатором этой программы. Привилегированный процесс (CAP_SYS_NICE) может устанавливать привязку к ЦПУ для любой программы.

Системный вызов sched_getaffinity() получает маску родственного процессора для процесса, указанного с помощью аргумента pid. Если pid равен 0, возвращается маска вызывающего процесса.

#define _GNU_SOURCE

#include

int sched_getaffinity(pid_t pid, size_t len, cpu_set_t *set);

Возвращает 0 при успешном завершении или –1, если произошла ошибка

Маска родственного процессора возвращается внутри структуры cpu_set_t, на которую указывает аргумент set. Аргументу len нужно присвоить число байтов в структуре (то есть sizeof(cpu_set_t)). С помощью макроса CPU_ISSET() можно определить, какие процессоры находятся в возвращенном значении set.

Если маска родственного процессора заданного процесса больше не была никаким образом изменена, вызов sched_getaffinity() возвращает набор, состоящий из всех процессоров в системе.

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

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

Системные вызовы sched_setaffinity() и sched_getaffinity() доступны только в Linux.

Программы t_sched_setaffinity.c и t_sched_getaffinity.c, которые можно найти в подкаталоги procpri внутри архива с исходными кодами, прилагающегося к этой книге, демонстрируют применение вызовов sched_setaffinity() и sched_getaffinity().

35.5. Резюме
Перейти на страницу:

Похожие книги