CPU_SET(3) | Руководство программиста Linux | CPU_SET(3) |
CPU_SET, CPU_CLR, CPU_ISSET, CPU_ZERO, CPU_COUNT, CPU_AND, CPU_OR, CPU_XOR, CPU_EQUAL, CPU_ALLOC, CPU_ALLOC_SIZE, CPU_FREE, CPU_SET_S, CPU_CLR_S, CPU_ISSET_S, CPU_ZERO_S, CPU_COUNT_S, CPU_AND_S, CPU_OR_S, CPU_XOR_S, CPU_EQUAL_S - макросы для работы с наборами ЦП
#define _GNU_SOURCE /* Смотрите feature_test_macros(7) */ #include <sched.h>
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);
int CPU_COUNT(cpu_set_t *set);
void CPU_AND(cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_OR(cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_XOR(cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2);
int CPU_EQUAL(cpu_set_t *set1, cpu_set_t *set2);
cpu_set_t *CPU_ALLOC(int num_cpus); void CPU_FREE(cpu_set_t *set); size_t CPU_ALLOC_SIZE(int num_cpus);
void CPU_ZERO_S(size_t setsize, cpu_set_t *set);
void CPU_SET_S(int cpu, size_t setsize, cpu_set_t *set); void CPU_CLR_S(int cpu, size_t setsize, cpu_set_t *set); int CPU_ISSET_S(int cpu, size_t setsize, cpu_set_t *set);
int CPU_COUNT_S(size_t setsize, cpu_set_t *set);
void CPU_AND_S(size_t setsize, cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_OR_S(size_t setsize, cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2); void CPU_XOR_S(size_t setsize, cpu_set_t *destset, cpu_set_t *srcset1, cpu_set_t *srcset2);
int CPU_EQUAL_S(size_t setsize, cpu_set_t *set1, cpu_set_t *set2);
Набор ЦП описывается структурой данных cpu_set_t. Набор ЦП используется в sched_setaffinity(2) и подобных интерфейсах.
Тип данных cpu_set_t реализован в виде битовой маски. Однако структуру данных следует считать «чёрным ящиком»: все действия с наборами ЦП следует выполнять с помощью макросов, описанных на этой странице.
Для работы с набором ЦП set предоставляются следующие макросы:
Макросы, имеющие аргумент cpu, не вызывают побочных эффектов, все перечисленные выше макросы могут использовать аргумент более одного раза.
Значение первого ЦП системы в cpu обозначается как 0, значение следующего ЦП в cpu равно 1 и т. д. Нельзя предполагать о доступности каких-либо ЦП, или что набор ЦП непрерывен, так как ЦП могут динамически отключаться или вообще отсутствовать. Константой CPU_SETSIZE (в настоящее время 1024) задаётся значение на 1 большее, чем максимальный номер ЦП, который можно хранить в cpu_set_t.
Следующие макросы выполняют логические операции над наборами ЦП:
Так как некоторым приложениям может потребоваться наборы ЦП динамически изменяемых размеров (например, для выделения наборов больше, чем определено стандартным типом данных cpu_set_t), glibc предоставляет набор макросов для этого.
Следующие макросы используются для выделения и удаления наборов ЦП:
Макросы, чьи имена заканчиваются на «_S», аналогичны макросам с тем же именем без суффикса. Эти макросы выполняют те же задачи что и их аналоги, но они работают с динамически выделяемыми наборами ЦП, размер которых равен setsize байт.
Макросы CPU_ISSET() и CPU_ISSET_S() возвращают ненулевое значение, если cpu есть в set; в противном случае возвращается 0.
Макросы CPU_COUNT() и CPU_COUNT_S() возвращают количество ЦП в set.
Макросы CPU_EQUAL() и CPU_EQUAL_S() возвращают ненулевое значение, если два набора ЦП одинаковы; в противном случае возвращается 0.
При успешном выполнении макрос CPU_ALLOC() возвращает указатель, при ошибке возвращается NULL (ошибки те же, что и у malloc(3)).
Макрос CPU_ALLOC_SIZE() возвращает количество байт, требуемое для хранения набора ЦП указанных элементов.
Остальные функции не возвращают никаких значений.
Макросы CPU_ZERO(), CPU_SET(), CPU_CLR() и CPU_ISSET() добавлены в glibc версии 2.3.3.
Макрос CPU_COUNT() впервые появилась в glibc версии 2.6.
Макросы CPU_AND(), CPU_OR(), CPU_XOR(), CPU_EQUAL(), CPU_ALLOC(), CPU_ALLOC_SIZE(), CPU_FREE(), CPU_ZERO_S(), CPU_SET_S(), CPU_CLR_S(), CPU_ISSET_S(), CPU_AND_S(), CPU_OR_S(), CPU_XOR_S() и CPU_EQUAL_S() впервые появились в glibc версии 2.7.
Данные интерфейсы есть только в Linux.
Для создания копии набора ЦП используйте memcpy(3).
Так как наборы ЦП это битовые маски, выделяемые в единицах длинных слов, реальное количество ЦП в динамически выделенном наборе ЦП будет округлено до следующего кратного sizeof(unsigned long). Приложение должно считать содержимое этих дополнительных бит неопределённым.
Несмотря на похожесть имён, заметим, что константа CPU_SETSIZE определяет количество ЦП в типе данных cpu_set_t (то есть, эффективное количество битов в битовой маске), в то время как аргумент setsize макросов CPU_*_S() — это размер в байтах.
Типы данных параметров и возвращаемых значений, показанных в ОБЗОРЕ — подсказки, что ожидается в каждом случае. Однако так как эти интерфейсы реализованы как макросы, компилятор не обязательно поймает все ошибки приведения типов, если вы нарушите предположения.
На 32-разрядных платформах в glibc 2.8 и ранее CPU_ALLOC () выделяет вдвое больше пространства, как требуется, и CPU_ALLOC_SIZE() возвращает значение вдвое большее, чем должно. Эта ошибка не должна влиять на семантику программы, но приводит к трате впустую памяти и менее эффективной работе макросов для динамически выделяемых наборов ЦП. Эти ошибки исправлены в glibc версии 2.9.
Следующая программа показывает использование некоторых макросов, работающих с динамически выделяемыми наборами ЦП.
#define _GNU_SOURCE #include <sched.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <assert.h> int main(int argc, char *argv[]) { cpu_set_t *cpusetp; size_t size; int num_cpus, cpu; if (argc < 2) { fprintf(stderr, "Использование: %s <количество-ЦП>\n", argv[0]); exit(EXIT_FAILURE); } num_cpus = atoi(argv[1]); cpusetp = CPU_ALLOC(num_cpus); if (cpusetp == NULL) { perror("CPU_ALLOC"); exit(EXIT_FAILURE); } size = CPU_ALLOC_SIZE(num_cpus); CPU_ZERO_S(size, cpusetp); for (cpu = 0; cpu < num_cpus; cpu += 2) CPU_SET_S(cpu, size, cpusetp); printf("CPU_COUNT() набора: %d\n", CPU_COUNT_S(size, cpusetp)); CPU_FREE(cpusetp); exit(EXIT_SUCCESS); }
sched_setaffinity(2), pthread_attr_setaffinity_np(3), pthread_setaffinity_np(3), cpuset(7)
2019-03-06 | Linux |