cpu = get_cpu(); /* получить номер текущего процессора и запретить
вытеснение в режиме ядра */
my_percpu[cpu]++;
printk("значение данных процессора cpu=%d равно %ld\n",
cpu, my_percpu[cpu]);
put_cpu(); /* разрешить вытеснение в режиме ядра */
Обратите внимание, что не нужно использовать никаких блокировок, потому что данные уникальны для каждого процессора. Поскольку никакой процессор, кроме текущего, не может обратиться к соответствующему элементу данных, то не может возникнуть и никаких проблем с конкурентным доступом, а следовательно, текущий процессор может безопасно обращаться к данным без блокировок.
Возможность вытеснения процессов в режиме ядра— единственное, из-за чего могут возникнуть проблемы. В преемптивном ядре могут возникнуть следующие две проблемы.
• Если выполняющийся код вытесняется и позже планируется для выполнения на другом процессоре, то значение переменной cpu
• Если некоторый другой код вытеснит текущий, то он может параллельно обратиться к переменной my_percpu
Однако все опасения напрасны, потому что вызов функции get_cpu()
put_cpu() разрешает вытеснение кода в режиме ядра. Обратите внимание, что функция smp_processor_id(), которая также позволяет получить номер текущего процессора, не запрещает вытеснения кода в режиме ядра, поэтому для безопасной работы следует использовать указанный выше метод.Новый интерфейс percpu
В ядрах серии 2.6 предложен новый интерфейс, именуемый
Рассмотренный ранее метод работы с данными, которые связаны с определенным процессором, является вполне законным. Новый интерфейс возник из необходимости иметь более простой и мощный метод работы с данными, связанными с процессорами, на больших компьютерах с симметричной мультипроцессорностью.
Все подпрограммы объявлены в файле
mm/slab.с и .Работа с данными, связанными с процессорами, на этапе компиляции
Описать переменную, которая связана с определенным процессором, на этапе компиляции можно достаточно просто следующим образом.
DEFINE_PER_CPU(type, name);
Это описание создает переменную типа type
name, которая имеет интерфейс связи с каждым процессором в системе. Если необходимо объявить соответствующую переменную с целью избежания предупреждений компилятора, то необходимо использовать следующий макрос.DECLARE_PER_CPU(type, name);
Работать с этими переменными можно с помощью функций get_cpu_var()
put_cpu_var(). Вызов функции get_cpu_var() возвращает l-значение (левый операнд, l-value) указанной переменной на текущем процессоре. Этот вызов также запрещает вытеснение кода в режиме ядра, а соответственный вызов функции put_cpu_var() разрешает вытеснение.get_cpu_var(name)++; /* увеличить на единицу значение переменной
name, связанное с текущим процессором */
put_cpu_var(); /* разрешить вытеснение кода в режиме ядра */
Можно также получить доступ к переменной, связанной с другим процессором.
per_cpu(name, cpu)++; /* увеличить значение переменной name
на указанном процессоре */
Использовать функцию per_cpu()