.\" -*- coding: UTF-8 -*- .\" Copyright (C) 2002 Robert Love .\" and Copyright (C) 2006, 2015 Michael Kerrisk .\" .\" SPDX-License-Identifier: GPL-2.0-or-later .\" .\" 2002-11-19 Robert Love - initial version .\" 2004-04-20 mtk - fixed description of return value .\" 2004-04-22 aeb - added glibc prototype history .\" 2005-05-03 mtk - noted that sched_setaffinity may cause thread .\" migration and that CPU affinity is a per-thread attribute. .\" 2006-02-03 mtk -- Major rewrite .\" 2008-11-12, mtk, removed CPU_*() macro descriptions to a .\" separate CPU_SET(3) page. .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH sched_setaffinity 2 "3 мая 2023 г." "Linux man\-pages 6.05.01" .SH ИМЯ sched_setaffinity, sched_getaffinity \- устанавливает и получает процессорную маску увязывания для нити .SH LIBRARY Standard C library (\fIlibc\fP, \fI\-lc\fP) .SH СИНТАКСИС .nf \fB#define _GNU_SOURCE\fP /* Смотрите feature_test_macros(7) */ \fB#include \fP .PP \fBint sched_setaffinity(pid_t \fP\fIpid\fP\fB, size_t \fP\fIcpusetsize\fP\fB,\fP \fB const cpu_set_t *\fP\fImask\fP\fB);\fP \fBint sched_getaffinity(pid_t \fP\fIpid\fP\fB, size_t \fP\fIcpusetsize\fP\fB,\fP \fB cpu_set_t *\fP\fImask\fP\fB);\fP .fi .SH ОПИСАНИЕ Процессорной маской увязывания нити задаётся набор процессоров, на которых разрешено выполняться нити. В многопроцессорных системах задание процессорной маски увязывания можно использовать для получения большей производительности. Например, выделение специального процессора определённой нити (т.е., задание в процессорной маске увязывания для нити одного ЦП и исключение этого ЦП из процессорных масок увязывания для остальных нитей) обеспечивает максимальную скорость выполнения этой нити. Ограничение для нити одним ЦП также исключает сокращение производительности в следствие недостоверности данных кэша, которая возникает, когда нить прекращает выполнение на одном ЦП и затем продолжает выполнение на другом. .PP Маска увязывания ЦП представляется в виде структуры \fIcpu_set_t\fP, «набором процессоров», на которую указывает \fImask\fP. В \fBCPU_SET\fP(3) описаны макросы для изменения набора ЦП. .PP Вызов \fBsched_setaffinity\fP() устанавливает маску увязывания ЦП \fImask\fP для нити, чей ID указан в \fIpid\fP. Если значение \fIpid\fP равно нулю, то используется вызывающая нить. В аргументе \fIcpusetsize\fP задаётся количество данных (в байтах), на которые указывает \fImask\fP. Обычно его значение указывается как \fIsizeof(cpu_set_t)\fP. .PP Если нить, указанная в \fIpid\fP, в данный момент не выполняется на одном из ЦП, заданном в \fImask\fP, то эта нить переносится на один из процессоров, назначаемых \fImask\fP. .PP Вызов \fBsched_getaffinity\fP() записывает в структуру \fIcpu_set_t\fP, на которую указывает \fImask\fP, значение маски увязывания ЦП для нити, чей ID указан в \fIpid\fP. В аргументе \fIcpusetsize\fP задаётся размер \fImask\fP (в байтах). Если значение \fIpid\fP равно нулю, то возвращается маска вызывающей нити. .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" On success, \fBsched_setaffinity\fP() and \fBsched_getaffinity\fP() return 0 (but see "C library/kernel differences" below, which notes that the underlying \fBsched_getaffinity\fP() differs in its return value). On failure, \-1 is returned, and \fIerrno\fP is set to indicate the error. .SH ОШИБКИ .TP \fBEFAULT\fP Указан некорректный адрес памяти. .TP \fBEINVAL\fP В маске увязывания ЦП \fImask\fP указаны процессоры, которых физически нет в системе, и которые разрешены нити согласно любым ограничениям, которые могут налагаться \fIcpuset\fP cgroups или механизмом «cpuset», описанном в \fBcpuset\fP(7). .TP \fBEINVAL\fP (\fBsched_getaffinity\fP() and, before Linux 2.6.9, \fBsched_setaffinity\fP()) \fIcpusetsize\fP is smaller than the size of the affinity mask used by the kernel. .TP \fBEPERM\fP (\fBsched_setaffinity\fP()) Вызывающая нить не имеет достаточно прав. Вызывающему требуется иметь эффективный пользовательский ID равный реальному пользовательскому ID или эффективному пользовательскому ID нити, указанной в \fIpid\fP, или он должен обладать мандатом \fBCAP_SYS_NICE\fP в пространстве имён пользователя нити \fIpid\fP. .TP \fBESRCH\fP Нить с идентификатором \fIpid\fP не найдена. .SH СТАНДАРТЫ Linux. .SH ИСТОРИЯ Linux 2.5.8, glibc 2.3. .PP Initially, the glibc interfaces included a \fIcpusetsize\fP argument, typed as \fIunsigned int\fP. In glibc 2.3.3, the \fIcpusetsize\fP argument was removed, but was then restored in glibc 2.3.4, with type \fIsize_t\fP. .SH ЗАМЕЧАНИЯ После вызова \fBsched_setaffinity\fP() набор процессоров, на которых действительно будет выполняться нить, вычисляется пересечением набора из аргумента \fImask\fP и набором процессоров, присутствующих в системе. В дальнейшем, система может ограничить набор процессоров нити, если задействован механизм «cpuset», описанный в \fBcpuset\fP(7). Эти ограничения на действительный набор процессоров, используемых для нити, без уведомления налагаются ядром. .PP Есть несколько способов определения количества процессоров в системе: по содержимому \fI/proc/cpuinfo\fP; с помощью \fBsysconf\fP(3) получить значение параметров \fB_SC_NPROCESSORS_CONF\fP и \fB_SC_NPROCESSORS_ONLN\fP; посчитать количество подкаталогов cpu в \fI/sys/devices/system/cpu/\fP. .PP В \fBsched\fP(7) приведено описание схемы планирования Linux. .PP Маска увязывания является атрибутом нити, которая может изменяться независимо для каждой нити в группе нитей. В аргументе \fIpid\fP можно передавать значение, возвращаемое вызовом \fBgettid\fP(2). При значении \fIpid\fP равным 0 будет установлен атрибут вызывающей нити, а при передаче значения, возвращаемого вызовом \fBgetpid\fP(2), устанавливается атрибут главной нити группы нитей (при работе с программным интерфейсом POSIX используйте функцию \fBpthread_setaffinity_np\fP(3) вместо \fBsched_setaffinity\fP()). .PP Параметр начальной загрузки \fIisolcpus\fP можно использовать для изоляции одного и более ЦП во время загрузки, и ни один процесс не будет запланирован к выполнению на этих ЦП. После использования этого параметра единственный способ запланировать процессы на изолированных ЦП — использовать \fBsched_setaffinity\fP() или механизм \fBcpuset\fP(7). Подробности смотрите в файле исходного кода ядра \fIDocumentation/admin\-guide/kernel\-parameters.txt\fP. Согласно тексту файла, \fIisolcpus\fP является предпочтительным механизмом изоляции ЦП (по сравнению с ручным увязыванием ЦП всех процессов в системе). .PP Потомок, создаваемый с помощью \fBfork\fP(2), наследует маску увязывания ЦП. Маска увязывания сохраняется при вызове \fBexecve\fP(2). .SS "Отличия между библиотекой C и ядром" В данной справочной странице описан интерфейс glibc для вызовов увязывания ЦП. Интерфейс реальных системных вызов чуть отличается: аргумент \fImask\fP имеет тип \fIunsigned long\ *\fP, отражая факт того, что используемая реализация наборов ЦП представляет собой просто битовую маску. .PP При успешном выполнении ядерный системный вызов \fBsched_getaffinity\fP() возвращает количество скопированных в буфер \fImask\fP байт; минимальным значением будет \fIcpusetsize\fP и размер (в байтах) типа данных \fIcpumask_t\fP, который используется в ядре для представления процессорной битовой маски. .SS "Работа систем с масками увязывания ЦП большого размера" .\" FIXME . See https://sourceware.org/bugzilla/show_bug.cgi?id=15630 .\" and https://sourceware.org/ml/libc-alpha/2013-07/msg00288.html Лежащие в основе системные вызовы (которые представляют маски ЦП в виде маски битов с типом \fIunsigned long\ *\fP) не накладывают ограничений на размер маски ЦП. Однако, тип данных \fIcpu_set_t\fP, используемый в glibc, имеет постоянный размер 128 байт, то есть максимальный номер представляемых ЦП равен 1023. Если ядерная маска увязывания ЦП больше 1024, то вызовы вида: .PP .in +4n .EX sched_getaffinity(pid, sizeof(cpu_set_t), &mask); .EE .in .PP завершается ошибкой \fBEINVAL\fP; ошибка выдаётся подлежащим системным вызовом в случае, когда размер \fImask\fP, указанный в \fIcpusetsize\fP, меньше чем размер маски увязывания используемой ядром (в зависимости от топологии ЦП системы, ядерная маска увязывания может быть значительно больше, чем количество активных ЦП в системе). .PP При работе в системах с ядерными масками увязывания ЦП большого размера, место под аргумент \fImask\fP должно выделяться динамически (смотрите \fBCPU_ALLOC\fP(3)). В настоящее время единственный способ сделать это — определить размер требуемой маски с помощью вызовов \fBsched_getaffinity\fP() с увеличиваемым размером маски (пока вызов не перестанет выдавать ошибку \fBEINVAL\fP). .PP Учтите, что \fBCPU_ALLOC\fP(3) может выделить несколько больший набор ЦП, чем запрашивается (так как наборы ЦП реализованы как битовые маски, выделяемые в объёмах \fIsizeof(long)\fP). Следовательно, \fBsched_getaffinity\fP() может задать биты за границами запрашиваемого выделяемого размера, так как ядро видит несколько дополнительных бит. Поэтому вызывающий должен пройтись по всем возвращённым битам, считая установленные и остановиться при достижении значения, полученного от \fBCPU_COUNT\fP(3) (а не останавливаться на количестве запрошенных к выделению бит). .SH ПРИМЕРЫ Программа, представленная ниже, создаёт дочерний процесс. Затем родитель и потомок назначают выполнение себя на указанных ЦП и выполняют одинаковые циклы, которые выполняются на ЦП какое\-то время. Перед завершением, родитель ждёт завершения потомка. Программа имеет три аргумента командной строки: номер ЦП для родителя, номер ЦП для потомка и количество итераций цикла, который будут выполнять оба процесса. .PP В примере работы, показанном ниже, количество реального времени и времени использованного ЦП при работе программы, будет зависеть он меж ядерного кэширования и будут ли процессы использовать одинаковый ЦП. .PP Сначала запустим \fBlscpu\fP(1) для определения, что эта система (x86) имеет по два потока выполнения в двух ЦП: .PP .in +4n .EX $ \fBlscpu | egrep \-i \[aq]core.*:|socket\[aq]\fP Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 .EE .in .PP Затем запустим подсчёт времени выполнения программы для трёх случаев: оба процесс выполняются на одном ЦП; оба процесса выполняются на разных ЦП одного ядра; оба процесса выполняются на разных ЦП разных ядер. .PP .in +4n .EX $ \fBtime \-p ./a.out 0 0 100000000\fP real 14.75 user 3.02 sys 11.73 $ \fBtime \-p ./a.out 0 1 100000000\fP real 11.52 user 3.98 sys 19.06 $ \fBtime \-p ./a.out 0 3 100000000\fP real 7.89 user 3.29 sys 12.07 .EE .in .SS "Исходный код программы" .\" SRC BEGIN (sched_setaffinity.c) \& .EX #define _GNU_SOURCE #include #include #include #include #include #include \& int main(int argc, char *argv[]) { int parentCPU, childCPU; cpu_set_t set; unsigned int nloops; \& if (argc != 4) { fprintf(stderr, "Usage: %s parent\-cpu child\-cpu num\-loops\en", argv[0]); exit(EXIT_FAILURE); } \& parentCPU = atoi(argv[1]); childCPU = atoi(argv[2]); nloops = atoi(argv[3]); \& CPU_ZERO(&set); \& switch (fork()) { case \-1: /* Error */ err(EXIT_FAILURE, "fork"); \& case 0: /* Child */ CPU_SET(childCPU, &set); \& if (sched_setaffinity(getpid(), sizeof(set), &set) == \-1) err(EXIT_FAILURE, "sched_setaffinity"); \& for (unsigned int j = 0; j < nloops; j++) getppid(); \& exit(EXIT_SUCCESS); \& default: /* Parent */ CPU_SET(parentCPU, &set); \& if (sched_setaffinity(getpid(), sizeof(set), &set) == \-1) err(EXIT_FAILURE, "sched_setaffinity"); \& for (unsigned int j = 0; j < nloops; j++) getppid(); \& wait(NULL); /* Wait for child to terminate */ exit(EXIT_SUCCESS); } } .EE .\" SRC END .SH "СМ. ТАКЖЕ" .ad l .nh \fBlscpu\fP(1), \fBnproc\fP(1), \fBtaskset\fP(1), \fBclone\fP(2), \fBgetcpu\fP(2), \fBgetpriority\fP(2), \fBgettid\fP(2), \fBnice\fP(2), \fBsched_get_priority_max\fP(2), \fBsched_get_priority_min\fP(2), \fBsched_getscheduler\fP(2), \fBsched_setscheduler\fP(2), \fBsetpriority\fP(2), \fBCPU_SET\fP(3), \fBget_nprocs\fP(3), \fBpthread_setaffinity_np\fP(3), \fBsched_getcpu\fP(3), \fBcapabilities\fP(7), \fBcpuset\fP(7), \fBsched\fP(7), \fBnumactl\fP(8) .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства был сделан Alexander Golubev , Azamat Hackimov , Hotellook, Nikita , Spiros Georgaras , Vladislav , Yuri Kozlov и Иван Павлов . .PP Этот перевод является бесплатной документацией; прочитайте .UR https://www.gnu.org/licenses/gpl-3.0.html Стандартную общественную лицензию GNU версии 3 .UE или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. .PP Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на .MT man-pages-ru-talks@lists.sourceforge.net .ME .