Главная » Ядро Linux » Выделение памяти, связанной с определенным процессором

0

В современных операционных системах  широко используются данные,  связанные с определенными процессорами (per-CPU  data).  Это данные, которые являются уникальными для  каждого  процессора. Данные,  связанные с  процессорами,  хранятся в массиве.  Каждый  элемент  массива соответствует своему  процессору системы.  Номер процессора является индексом в этом  массиве. Таким   образом была  реализована работа  с данными, связанными с определенным процессором, в ядрах  серии  2.4.  В таком  подходе  нет  ничего   плохого,  поэтому  значительная  часть  кода  ядра  в  серии   2.6 все  еще  использует этот  интерфейс.  Данные  объявляются следующим образом,

unsigned long my_percpu[NR_CPUS];

Доступ  к этим  данным выполняется, как  показано ниже.

int cpu;

cpu = get_cpu();  /* получить номер текущего процессора и запретить вытеснение в режиме ядра */

my_percpu[cpu]++;

printk("значение данных процессора cpu=%d равно %ld\n", cpu, my_percpu[cpu]);

put_cpu(); /* разрешить вытеснение в режиме ядра */

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

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

• Если  выполняющийся код  вытесняется  и  позже  планируется для  выполнения на  другом  процессоре,  то  значение переменной  cpu  больше  не  будет  действительным,  потому  что  эта  переменная будет  содержать номер  другого  процессо-

pa.  (По той же  причине, после получения номера текущего процессора, нельзя переходить в состояние ожидания.)

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

Однако все  опасения напрасны, потому что  вызов функции getcp u  (), которая возвращает номер текущего процессора,  также запрещает вытеснение в  режиме ядра. Соответствующий вызов функции put_cpu () разрешает вытеснение кода в режиме ядра. Обратите внимание, что  функция  smp_processor_icl (), которая также позволяет получить номер текущего процессора, не запрещает вытеснения кода в режиме ядра, поэтому для безопасной работы следует использовать указанный выше метод.

Источник: Лав,  Роберт. Разработка ядра  Linux, 2-е  издание. : Пер.  с англ.  — М.  : ООО  «И.Д.  Вильяме» 2006. — 448 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии