Во многих других UNIX-системах тоже имеются интерфейсы для управления привязкой к процессорам. Например, HP-UX и Solaris предоставляют системный вызов pset_bind().
Системный вызов sched_setaffinity() привязывает к ЦПУ процесс, заданный с помощью аргумента pid. Если pid равен 0, изменения будут применены к вызывающему процессу.
#define _GNU_SOURCE
#include
int sched_setaffinity(pid_t
Возвращает 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 *
void CPU_SET(int
void CPU_CLR(int
int CPU_ISSET(int
Возвращает истину (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).
Процессоры в наборе пронумерованы, начиная с нуля. В заголовочном файле
Аргумент 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
Возвращает 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().