ПРЕСС-ЦЕНТР

Новое поколение ОСРВ. LynxOS 5.0 и симметричная мультипроцессорная обработка данных

МКА: мир ВКТ 4/2008

С.В. Золотарев, А.В. Исаев

В данной статье рассматриваются впечатляющие возможности новой флагманской версии операционной системы реального времени (ОСРВ) LynxOS 5.0 компании LynuxWorks, отражающие основные тенденции в развитии ОСРВ и встраиваемых операционных систем. Именно вызовы нашего времени создали необходимость выпуска новой версии LynxOS 5.0, для того, чтобы разработчики получили адекватный продукт, соответствующий современному уровню развития многоядерных процессорных технологий. Поэтому основное внимание в статье уделено поддержке в LynxOS 5.0 симметричной мультипроцессорной обработки данных (Symmetric MultiProcessing - SMP) и, в частности, таким вопросам как планирование и синхронизация в среде SMP.

Новые тенденции в развитии ОСРВ и встраиваемых операционных систем

В 2006 году, в связи с появлением многоядерных аппаратных решений компании Intel, прогнозировалось, что через два года многоядерные системы станут основной платформой серверов, настольных компьютеров и ноутбуков, а в перспективе и встраиваемых систем [1]. Прогноз полностью оправдался, в том числе и в отношении встраиваемых систем. Конечно, в первую очередь это коснулось аппаратных средств [2], а затем уже программной поддержки. Пока на рынке встраиваемых систем не было массового использования многоядерных процессоров для архитектур x86 и PowerPC, потребность в их программной поддержке практически отсутствовала, однако в настоящее время картина существенно изменилась. Одной из основных тенденций в развитии ОСРВ и встраиваемых операционных систем в 2008 году стала поддержка многоядерной архитектуры и симметричной мультипроцессорной обработки данных. Все основные разработчики ОСРВ реализовали в своих новых версиях поддержку SMP: QNX Neutrino 6.3, VxWorks 6.6, LynxOS 5.0 (www.lynuxworks.com/rtos/rtos.php), Integrity 10.0, ThreadX/SMP. Без программной поддержки SMP на уровне операционной системы все преимущества многоядерной архитектуры, реализованные на аппаратном уровне, становятся практически малополезными возможностями, ничего не дающими пользователям. Заметим, однако, что уровень поддержки SMP сильно отличается у разных ОСРВ. Одна из наиболее развитых поддержек SMP реализована в LynxOS 5.0. Причем следует особо отметить, что реализация в LynxOS 5.0 поддержки SMP не просто отражает общую тенденцию в развитии ОСРВ, а ориентирована, прежде всего, на значительное улучшение основного показателя этого класса операционных систем – характеристик реального времени, таких как время реакции на события и детерминизм поведения при любых нагрузках. Очень важно, чтобы отечественные разработчики по достоинству оценили новые возможности LynxOS 5.0 и в полной мере воспользовались конкурентными преимуществами, которые предоставляет данная ОСРВ.

Немного об истории развития LynxOS

Прежде чем перейти к детальному рассмотрению LynxOS 5.0, хотелось бы напомнить об основных этапах развития этой операционной системы и ее вкладе в становлении многих основополагающих подходов в области ОСРВ. Именно в LynxOS были впервые реализованы многие идеи, впоследствии подхваченные другими поставщиками операционных систем реального времени. Например, согласованность со стандартом POSIX или поддержка Linux-приложений.

Компания LynuxWorks была основана в 1988 и вышла на рынок с первой в мире реализацией UNIX реального времени: операционной системой LynxOS. Первоначально компания называлась Lynx Real-Time Systems. В мае 2000 года название компании изменилось на LynuxWorks, являясь отражением новой стратегии, отраженной в формуле: Lynx + Linux = Lynux. С одной стороны, эта формула отражала факт разработки компанией своей собственной версии продукта класса Embedded Linux (BlueCat Linux), с другой стороны, стремлением в самой ОСРВ LynxOS обеспечить определенный уровень совместимости с Linux, который впоследствии воплотился в так называемый уровень двоичной совместимости с Linux: Linux ABI (ABI – Application Binary Interface).

Первая версия LynxOS была написана в 1986 году в Далласе (Техас) для процессора Motorola 68010. В 1988-89 году LynxOS была портирована на Intel 80386.

LynxOS 2.0 – февраль 1991. Поддерживала относительно небольшой набор возможностей, таких как двоичные семафоры, разделяемая память, асинхронные события, межпроцессное взаимодействие, непрерывные файлы. В конце 1994 года LynxOS стала поддерживать процессоры PowerPC 60x, что явилось предпосылкой к значительному расширению рынка использования LynxOS и, в конечном счете, к завоеванию лидирующих позиций LynxOS среди других ОСРВ именно в сегменте оборудования на платформе PowerPC. С сентября 1995 года были начаты работы по портации LynxOS на процессоры SPARC-архитектуры.

LynxOS 3.0 – март 1998 года. Поддерживается широкий спектр процессорных архитектур: x86 (Intel 386, 486, Pentium, Pentium Pro, Pentium II), PowerPC (603, 603e, 603ev, 604, 604e, 604er, PowerQUICC 860,821, 750), 68K (MC68030, MC68040, MC68LC040, MC68060), SPARC (microSPARC, microSPARC II). Для всех указанных платформ разработка могла вестись как в Native, так и в кросс-среде. В качестве графической среды использовалась X Window (X11R6).

LynxOS 4.0 – июнь 2000 года. Основные целевые платформы: x86, PowerPC, MIPS (специальная версия для HP). Кросс-платформы Windows 2K, XP, Linux RedHat 7.2 и выше, Solaris 2.7 и выше. Поддержка Linux ABI для ядра Linux 2.4.x. Расширение сетевых возможностей, в том числе поддержка IPv6 и IPSec.

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

Основными аппаратными платформами, которые поддерживаются всеми версиями LynxOS, являются x86 и PowerPC. Кроме того, существуют специальные заказные версии для процессоров MIPS. Кроме LynxOS компания LynuxWorks предлагает пользователям еще четыре системных продукта: LynxOS-178 [3], LynxOS-SE, LynxSecure[4], BlueCat Linux [5].

Основные возможности LynxOS

  • Операционная система жесткого реального времени, поддерживающая многопроцессные и многопотоковые приложения [6].
  • Cогласованность (conformance) со стандартом POSIX. Полностью поддерживается стандарт POSIX.1003.1a, а также подразделы POSIX.1003.1b и POSIX.1003.1c. LynxOS сертифицирована на согласованность с POSIX 1003.1-1996 в 1996 году для платформ Intel и PowerPC. Информацию об этом можно найти на сайте IEEE http://standards.ieee.org/regauth/posix/posix2.html. LynxOS сертифицирована по POSIX 1003.1-1996 компанией Mindcraft, Inc., являющейся IEEE POSIX Accredited POSIX Testing Laboratory по набору тестов NIST FIPS 151-2 Conformance Test Suite.. Поясним содержание указанных выше стандартов POSIX. 1003.1a (OS Definition) определяет основные интерфейсы ОС, управление заданиями, сигналы, функции файловой системы и работы с устройствами, группы пользователей, конвейеры, FIFO-буферы. 1003.1b (Realtime Extensions) описывает расширения реального времени, такие как сигналы реального времени, диспетчеризация по приоритетам, таймеры, синхронный и асинхронный ввод-вывод, семафоры, разделяемая память, сообщения. 1003.1c (Threads) определяет функции поддержки потоков (нитей), такие как управление потоками, атрибуты потоков, мьютексы, диспетчеризация.
  • Совместимость с Linux. Программы, написанные и откомпилированные в ОС Linux, могут запускаться и работать в среде LynxOS без каких-либо изменений в исходных текстах и без перекомпилирования. Это свойство LynxOS является уникальным для систем реального времени и очень удобным для пользователей (например, в случае отсутствия исходных текстов). LynxOS обеспечивает совместимость с Linux на уровне ABI (Application Binary Interface), уровне форматов объектных файлов, вызовов API, динамически подключаемых библиотек, компоновки и загрузки на этапе выполнения.
  • Многоплатформность. Поддерживает множество аппаратных архитектур (x86, PowerPC, MIPS) для оборудования различных фирм-производителей.
  • Современные сетевые средства: IPv4 и IPv6, IPSec/IKE/VPN, QoS, протоколы TCP, UDP, ICMP, IGMP, ARP, RARP, DHCP, NAT, RPC, NTPv3, RIP, RIPv2, DVMRP, BGP4, OSPF, OSPFv2, SNMP v1, v2 и v3 (рис.1) .

Сетевые возможности LynxOS
Рис.1 Сетевые возможности LynxOS

Новые возможности LynxOS в версии 5.0

Основной отличительной особенностью версии LynxOS 5.0 является поддержка многоядерных конфигураций и архитектуры симметричной мультипроцессорной обработки данных (SMP). Подробно об этом мы поговорим ниже. Надо сказать, что в LynxOS поддержка многоядерных конфигураций была в старых версиях LynxOS вплоть до версии 2.5, но потом (по неизвестным автору причинам) перестала поддерживаться.

С чисто пользовательской точки зрения, отметим следующие важные отличия LynxOS 5.0 от версий LynxOS 4.0/4.2:

  • Обновленный набор средств разработки GNU toolchain, основанный на GCC, G++ версии 3.4.3 и GDB версии 6.5. В предыдущих версиях LynxOS поддерживались значительно более старые версии GCC и GDB: в LynxOS 4.0 версии 2.95.3 и 4.17 соответственно, в LynxOS 4.2 версии 3.2.2 и 4.17 соответственно.
  • В LynxOS 5.0 разработка приложений и драйверов теперь доступна только в кросс-среде (Linux или Windows), в том время как в предыдущих версиях (4.0/4.2) дополнительно поддерживалась native среда разработки (то есть среда разработки в самой LynxOS).
  • В LynxOS 5.0 все библиотеки поставляются только в виде многопотоковых версий, в том время как в предыдущих версиях (4.0/4.2) поддерживались как однопотоковые, так и многопотоковые версии библиотек. Это обеспечивает универсальность разрабатываемого пользователем программного обеспечения.
  • Поддержка файловой системы FAT16/32, что позволяет использовать файлы из-под DOS и Windows.
  • Все файлы в системе стали теперь в ELF формате. В предыдущих версиях, часть файлов была в формате coff (например, ядро), часть в формате elf (например, приложения пользователя), что создавало определенные неудобства для пользователя.
  • Поддержка языка Ada (GNAT 3.4.3)
  • Полная поддержка многопотоковой версии C++.
  • Новый, более современный уровень согласованности с POSIX: POSIX—POSIX 1003.1-2003 PSE 53/54
  • Двоичная ABI совместимость c Linux 2.6. В предыдущих версиях LynxOS (4.0/4.2) поддерживалась с Linux 2.4. Новая версия Linux ABI позволяет запускать в среде LynxOS 5.0 такие серьезные приложения как Oracle 9, Apache, ACE-TAO, PostGres и QT.
  • Новейшая интегрированная среда разработки Luminosity 3.0, в основе которой лежит популярная инструментальная платформа Eclipse. Luminosity представляет собой полнофункциональную интегрированную среду разработки на базе Java, предназначенную для использования в системах LynxOS для создания, редактирования, компилирования, контроля и отладки встраиваемых приложений и программ реального времени.

На момент написания статьи возможность использования LynxOS 5.0 была обеспечена (см. http://www.lynuxworks.com/board-support/all-lynxos.php) для аппаратной платформы x86 (процессоров Intel и AMD), а также для нескольких плат c процессором PowerPC (MPC74xx, MPC8640/8641D) от компаний GE Fanuc Intelligent Platforms, Curtiss-Wright и Freescale Semiconductor. .

Поддержка SMP-архитектуры в LynxOS 5.0

LynxOS 5.0 может работать в режиме SMP на платах c несколькими процессорными ядрами или процессорами. Чтобы обеспечить поддержку SMP в LynxOS 5.0, было сделано несколько изменений в ядре операционной системы и библиотеках пользовательского уровня. Эти изменения оказывают определенное влияние на процесс разработки заказных ядер операционной системы LynxOS и приложений пользователя. Далее будут вкратце описаны изменения и детализированы особенности разработки в LynxOS 5.0, связанные с поддержкой SMP. Главной особенностью систем с архитектурой SMP является наличие общей физической памяти, разделяемой всеми процессорами. При обращении к памяти все процессоры имеют равные права и одну и ту же адресацию для всех ячеек памяти. Поэтому SMP-архитектура называется симметричной.

Два подхода к планированию очередей в SMP среде

Существует два подхода к организации потоков очередей на выполнение в среде SMP:

  • Первый подход: на каждый процессор формируется своя отдельная очередь потоков на выполнение. Другими словами, если, например, в системе есть два процессора (ядра), то к каждому процессору будет организовываться своя отдельная очередь (то есть будет две очереди потоков).
  • Второй подход: для всех процессоров формируется одна общая очередь потоков на выполнение. Планировщик определяет, на каком из процессоров будет выполняться поток в данный момент.

Рассмотрим преимущества и недостатки каждого из этих подходов и дадим обоснование подхода, используемого в LynxOS 5.0.

Планирование в операционных системах общего назначения

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

Операционные системы общего назначения, такие как Linux, FreeBSD, и Solaris достигают этого, поддерживая для каждого процессора свою собственную очередь потоков. Каждый поток остается на одном процессоре в течение относительно длительного периода времени. Время от времени, планировщик уравновешивает загрузку процессоров, перемещая потоки с сильно нагруженных процессоров на слабо загруженные процессоры (происходит так называемая балансировка загрузки процессоров). Этот подход часто называют подходом со многими очередями на выполнение. Подход со многими очередями на выполнение хорош для повышения общей производительности системы. Однако, он имеет недостаток с точки зрения времени отклика в реальном времени, так как только поток становится готовым к выполнению, он должен ждать на своем процессоре, пока на нем закончится работа потока с более высоким приоритетом. Даже в случае, если другой процессор в системе – свободен или выполняет потоки с более низким приоритетом. Балансировка загрузки происходит достаточно редко и не может оказать помощь этому потоку (например, в случае, если другие процессоры заняты большим количеством потоков с более низким приоритетом). В качестве дополнительной возможности планировщик может позволить пользователю связывать поток с одним процессором или рядом процессоров. Такие потоки не могут быть перемещены на другие процессоры даже при балансировке загрузки. Эту особенность называют привязкой к процессору (affinity) . Эффект привязки к процессору влияет и на производительность и на время отклика в реальном времени еще более явно, чем подход со многими очередями на выполнение. Однако, в отличие от числа очередей на выполнение, привязка к процессору является дополнительной (опциональной) возможностью. Пользователь может выбрать, использовать ли ему ее или нет, но только после тщательного рассмотрения и тестирования. В настоящее время LynxOS 5.0 не поддерживает возможность привязки к процессору. Однако это свойство может быть добавлено позже в виде патчей или после появления новых релизов операционной системы.


Планирование в LynxOS 5.0

Будучи операционной системой жесткого реального времени с планировщиком со строгим вытеснением по приоритетам, LynxOS рассматривает время отклика в реальном времени как более важный параметр, чем суммарная производительность системы. Поэтому был выбран подход с одной очередью на выполнение. В LynxOS 5.0 существует только одна очередь потоков на выполнение в системе (или в разделе, если версия LynxOS обеспечивает поддержку изолированных разделов, например, как в LynxOS-178). Когда поток становится готовым к работе, планировщик немедленно запускает его на одном из процессоров с самым низким текущим приоритетом выполняемого потока. Этот подход гарантирует, что в системе с N процессорами в любой момент времени выполняются N потоков с самым высоким приоритетом. С другой стороны, перемещение потоков между процессорами происходит более часто, чем в подходе с множеством очередей на выполнение, и таким образом приводит к сокращению суммарной производительности системы. Многие современные многоядерные архитектуры подвержены этому эффекту намного меньше, т.к. имеют в своем составе общий для всех ядер кэш 2-го или 3-го уровня, значительно ускоряющий перемещение контекста потока между ядрами.

Механизмы синхронизация в LynxOS 5.0 на уровне ядра

В LynxOS 5.0 для обеспечения работы в SMP среде были добавлены новые механизмы синхронизации на уровне ядра операционной системы: атомарные операции, спин-блокировки (spin lock) ядра, большая блокировка ядра (BKL, Big Kernel Lock). Как нетрудно заметить, новые механизмы синхронизации имеют аналоги в Linux. Новые механизмы дополнили список механизмов синхронизации на уровне ядра, использовавшиеся для однопроцессорной архитектуры: семафоры ядра, запрет прерывания (на вызывающем процессоре), запрет вытеснения потока (на вызывающем процессоре).

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

Атомарные переменные и операции

LynxOS 5.0 поддерживает атомарный тип переменных [7], который является значением целого числа, хранимого в RAM, плюс ряд поддержанных аппаратными средствами операций для атомарных переменных (чтение, изменение, запись, тестирование и установка). Атомарные операции на атомарных переменных являются непрерываемыми для всей системы, и поэтому полезны для синхронизации и других целей и в однопроцессорной и многопроцессорной среде. Рассмотрим на примере подсчета ссылок, для чего нужны атомарные переменные и операции над ними в SMP среде[8]. Пусть процесс хочет отказаться от своей доли в разделяемом ресурсе и узнать, владеет ли им кто-то еще, путем уменьшения счетчика этого разделяемого ресурса и проверки его на равенство нулю. Типичная последовательность действий может начинаться со следующего:

  1. Процессор загружает текущее значение счетчика (скажем, 2) в один из своих регистров.
  2. Процессор уменьшает это значение в своем регистре; теперь оно равно 1.
  3. Процессор записывает новое значение (1) обратно в память.
  4. Процессор решает, что поскольку значение равно 1, разделяемый объект используется каким-то другим процессом, поэтому не освобождает объект.

В однопроцессорных системах этот сценарий не вызывает проблем. Но в симметричных мультипроцессорных системах картина совершенно иная: а что будет, если окажется, что другой процессор выполняет ту же работу и в то же время?

Наихудший случай выглядит примерно так:

  1. Процессор А загружает текущее число (2) в один из своих регистров.
  2. Процессор В загружает текущее число (2) в один из своих регистров.
  3. Процессор А уменьшает значение в своем регистре; теперь оно равно 1.
  4. Процессор В уменьшает значение в своем регистре; теперь оно равно 1.
  5. Процессор А записывает новое значение (1) обратно в память.
  6. Процессор В записывает новое значение (1) обратно в память.
  7. Процессор А решает, что поскольку значение равно 1, этот разделяемый объект используется каким-то другим процессом, поэтому не освобождает его.
  8. Процессор В решает, что поскольку значение равно 1, этот разделяемый объект использует какой-то другой процесс, поэтому не освобождает его.

Число ссылок в памяти теперь должно быть равно 0, но вместо этого, оно равно 1. Оба процессора удалили свои ссылки на разделяемый объект, но ни один из них его не освободил. Каждый процессор выполнил именно то, что требовалось, и все равно возник неправильный результат. Проблема, безусловно, состоит в том, что процессоры не синхронизировали свои действия. Простейшим средством синхронизации ядра LynxOS в SMP-среде являются атомарные операции.

LynxOS 5.0 обеспечивает многие операции, которые могут быть атомарно выполнены над значением целого числа, расположенного в RAM. Атомарно означает, что операция появляется на всех процессорах и потоках в системе как единственный непрерываемый доступ памяти. Атомарные операции являются самыми быстрыми (по сравнению с другими методами синхронизации) доступными методами синхронизации в случае, когда для синхронизации доступа требуется только одно целое число, поскольку они позволяют пользователю избегать более тяжелых примитивов синхронизации, таких как семафоры и спин-блокировки. Однако атомарные операции обычно намного медленнее, чем соответствующие неатомарные операции. API для атомарных операций определено в заголовочном файле atomic_ops.h. Атомарные операции с целыми числами доступны как при работе ядра, так и в приложениях пользователя.
Все атомарные операции воздействуют на платформенно зависимую переменную типа atomic_t (называемую атомарной переменной). Целое значение числа, содержащееся в типе atomic_t, имеет тип atomic_value_t. Это, по крайней мере, 32-битовое число со знаком. Тип atomic_t преднамеренно определен так, чтобы переменные этого типа не могли применяться в выражениях на языке C с целыми числами, а только использовались с помощью API для атомарных операций.

Вызов atomic_init (av, v) инициализирует атомарную переменную av и устанавливает ее в указанное значение v. Все атомарные переменные должны инициализироваться прежде, чем они смогут использоваться. Другой способ инициализировать атомарную переменную состоит в том, чтобы присвоить ей начальное значение ATOMIC_INITIALIZER (v) при определении переменной, где v - ее начальное значение:
#include <atomic_ops.h>

atomic_t av1 = ATOMIC_INITIALIZER (0);
atomic_t av2;

atomic_init (av2, 0);

Операции над атомарными переменными приведены в Таблице 1.

Таблица 1: Операции над атомарными переменными

Операция
Описание
atomic_set (av, v)
Установить атомарную переменную в указанное значение.
atomic_get (av)
Возвратить текущее значение атомарной переменной.
atomic_add (av, v)
Добавить указанное значение к атомарной переменной и возвратить ее новое значение.
atomic_sub (av, v)
Вычесть указанное значение из атомарной переменной и возвратить ее новое значение
atomic_inc (av)
Увеличить на 1 значение атомарной переменной и возвратить ее новое значение.
atomic_dec (av)
Уменьшить на 1 значение атомарной переменной и возвратить ее новое значение.
atomic_xchg (av, v)
Установить значение атомарной переменной av в v и возвратить ее старое значение.
atomic_cmpxchg (av, v1, v2)
Взять два значения, v1 и v2. Если значение атомарной переменной равно v1, то установить ее в v2. В любом случае возвращается старое значение атомарной переменной.
atomic_or (av, v)
Сделать побитовое ИЛИ значения атомарной переменная с указанной битовой маской и сохранить результат в атомарной переменной. Никакое значение не возвращается.
atomic_and (av, v)
Сделать побитовое И значения атомарной переменной с указанной битовой маской и сохранить результат в атомарной переменной. Никакое значение не возвращается.
atomic_xor (av, v)
Сделать побитовое XOR значения атомарной переменной с указанной битовой маской и сохранить результат в атомарной переменной. Никакое значение не возвращается.
atomic_get_or (av, v)
Сделать побитовое ИЛИ значения атомарной переменной с указанной битовой маской и сохранить результат в атомарной переменной. Возвращается старое значение.
atomic_get_and (av, v)
Сделать побитовое И значения атомарной переменной с указанной битовой маской и сохранить результат в атомарной переменной. Возвращается старое значение.

Барьеры памяти

В мультипроцессорной среде в небольшом количестве ситуаций должен быть обеспечен определенный порядок доступа к памяти процессора (загрузка и сохранение). LynxOS 5.0 обеспечивает ряд вызовов для обеспечения строгого порядка доступа к памяти процессора, названного барьером памяти.

Поясним, для чего нужно было ввести барьеры памяти в SMP-среде. Синхронизация доступа к разделяемому ресурсу требует команд доступа к памяти (сохранения и загрузки) для того, чтобы выполняться и стать видимым для всех процессоров в системе в определенном порядке. Обычно программист ожидает, что доступ к памяти будет выполнен в том же самом порядке, в котором он появляется в коде программы. Однако, без дополнительных уловок, о которых будет написано ниже, это может оказаться неправильным, потому что современные оптимизирующие компиляторы могут переупорядочить инструкции процессора (в общем случае) и доступ к памяти (в частности) для того, чтобы достигнуть лучшей производительности. Например: если программа сохраняет 1, а затем 0 в то же самое место памяти, то компилятор может исключить первое сохранение. Однако, если первое сохранение было блокированием ресурса, а второе было разблокированием ресурса, то оптимизация компилятора приведет к неправильной работе программы.

Современные процессоры порождают другую проблему: большинство современных архитектур процессоров могут выполнять программу не в том порядке, как это написано в программе, а в порядке того, как данные становятся доступными (например, чтение из кэшируемой области памяти может быть выполнено прежде, чем будет выполнено предшествующее чтение из некэшируемой области памяти). У каждой архитектуры процессора есть ряд правил для упорядочения выполнения доступа к памяти, который называется моделью памяти. Во всех архитектурах отдельный процессор является последовательным, что заставляет программу, работающую на этом процессоре, выглядеть так, что все ее инструкции выполняются в порядке, указанном в программе. Однако это становится проблемой, когда есть другие «пользователи» на шине памяти, такие как внешние устройства ввода / вывода и, что наиболее важно, другие процессоры.

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

  1. Блокировка ресурса
  2. Доступ к ресурсу
  3. Разблокировка ресурса

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

LynxOS 5.0 обеспечивает ряд вызовов, чтобы обеспечить желательный порядок доступа к памяти - барьеры памяти. Есть два вида барьеров памяти: общий и специализированный. Общие барьеры памяти гарантируют выполнение своих функций в любой ситуации; однако, они являются обычно весьма медленными. В определенных случаях могут использоваться менее универсальные барьеры, которые называются специализированными барьерами.

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

Барьер памяти гарантирует, что доступы A и B будут выполнены прежде доступов C и D, но не гарантирует какого-либо порядка A относительно B и C относительно D.


API барьеров памяти определен в заголовочном файле membar.h. Барьеры памяти доступны и в ядре и в программах пользователя. Общие барьеры памяти приведены в Таблице 2.

Таблица 2. Общие барьеры памяти

Барьера памяти
Описание
membar_compiler ()
Барьер оптимизации компилятора.
Защищает компилятор от переупорядочения порядка операций доступа к памяти через этот барьер в целях оптимизации. Это также заставляет компилятор прекратить все предположения о содержимом памяти. Это - основной барьер: все другие барьеры включают функциональные возможности барьера оптимизации компилятора.
membar_store ()
Барьер сохранения
Гарантирует, что все сохранения, предшествующие этому барьеру (в порядке, указанном в программе), выполнены и глобально видимы перед сохранениями, следующими после этого барьера.
membar_load ()
Барьер загрузки
Гарантирует, что все загрузки, предшествующие этому барьеру (в порядке, указанном в программе), выполнены перед загрузками, следующими после этого барьера.
membar_all ()
полный барьер памяти.
Гарантирует, что все доступы к памяти (загрузки и сохранения), предшествовавшие этому барьеру (в порядке, указанном в программе) выполнены и глобально видимы перед доступами к памяти, следующими после этого барьера.


Специализированные барьеры памяти представлены в Таблице 3.

Таблица 3. Специализированные барьеры памяти

Барьер памяти
Описание
membar_io ()
Барьер ввода / вывода.
Этот барьер похож на полный барьер памяти, но только применяется для операций загрузки и сохранения в некэшируемую память. Некэшируемая память обычно используется для операций ввода / вывода, отображаемого на память. Таким образом, этот барьер имеет специфический интерес для программистов драйверов устройств.
membar_lock_enter ()
Барьер входа в блокировку.
Это - специализированный барьер, используемый с блокировками данных, чтобы гарантировать, что блокировка защищает данные. Он размещается непосредственно после сохранения памяти, которая захватывает блокировку.
membar_lock_exit ()
Барьер выхода из блокировки.
Это - специализированный барьер, используемый с блокировками данных, чтобы гарантировать, что блокировка защищает данные. Он размещается непосредственно перед сохранением памяти, которая освобождает блокировку.
membar_pause ()
Это - специализированный барьер, используемый с блокировками данных для выполнения короткой задержки.

Особенности генерация ядра LynxOS 5.0 для работы с несколькими процессорами (ядрами)

В контексте вопроса генерации ядра в LynxOS 5.0 в среде SMP, определимся, что понимается в LynxOS под термином процессор. Термин процессор (CPU) ссылается на отдельный кристалл с единственным процессорным ядром, индивидуальные ядра для многоядерного процессора или индивидуальные логические процессоры в случае технологии с поддержкой Hyper Threading (или аналогичной). Каждый процессор может выполнять один поток в каждый момент времени. Следовательно, система с N процессорами в состоянии выполнять одновременно N потоков.

При генерации ядра LynxOS 5.0 для работы с несколькими процессорами надо задать значение параметра NUM_CPUS в файле $ENV_PREFIX/sys/bsp.<bsp_name>/uparam.h. Если параметра NUM_CPUS нет в файле uparam.h, то LynxOS не будет поддерживать SMP и будет использовать только один процессор. Если параметр NUM_CPUS определен и равен 0 (по умолчанию), то LynxOS будет стараться определить число процессоров автоматически и использовать все найденные процессоры. Обычно этого достаточно для большинства конфигураций, но иногда желательно явно указать число процессоров, например, для того чтобы уменьшить время загрузки операционной системы. Если параметр NUM_CPUS равен -1, то число процессоров берется из установок BIOS. Если параметр NUM_CPUS равен 1, то LynxOS работает в однопроцессорной конфигурации. И, наконец, если параметр NUM_CPUS не меньше двух, то он задает число процессоров, которые должны использоваться операционной системой.

Специальные средства пользователя LynxOS 5.0 для работы в SMP среде

Нет никаких определенных требований к приложениям пользовательского уровня и библиотекам при работе в среде SMP. Введение SMP вызвало лишь некоторые изменения, видимые для пользователя. Большая часть приложений работают прекрасно в среде SMP без какой-либо модификации. В среде SMP процессы и потоки нормально синхронизируются стандартными примитивами (такими как мьютексы POSIX, семафоры и т.д.) тем же самым способом, как это сделано в случае однопроцессорной архитектуры. Дополнительно, могут использоваться атомарные операции и барьеры памяти, чтобы ввести новые дополнительные типы синхронизации. Довольно подробно это изложено в документе “LynxOS 4.x to LynxOS 5.0 Migration Kit Guide”.

Программист может узнать число процессоров в системе при использовании библиотечного вызова sysconf либо с помощью утилиты sysctl, например, следующим образом:

$ sysctl hw.ncpu
hw.ncpu: 2
$

Утилита ps показывает, на каком процессоре выполняется поток (для тех потоков, которые выполняются в настоящее время), или на каком процессоре поток выполнялся в последний раз (для других потоков). Из-за планирования с вытеснением по приоритетам в LynxOS, перемещение потоков с одного процессора на другой процессор происходит довольно часто. Информация процессора, показанная утилитами, является снимком состояния системы на какой-то момент времени, и не отражает все изменения состояния системы во время выполнения утилиты ps.

Говоря о специальных средствах работы пользователя в SMP среде, следует упомянуть об аппаратных средствах отладки, поддерживающих отладку программного обеспечения многоядерных систем. В частности, для отладки приложений и ядра LynxOS для многопроцессорных и многоядерных систем на PowerPC можно использовать JTAG-отладчики PowerDebug компании Lauterbach (www.lauterbach.com). JTAG-отладчики PowerDebug поставляются с собственной интегрированной программной средой PowerView, которая позволяет настраиваться на конкретную операционную систему и, в том числе, на LynxOS. Интегрированная среда отладки PowerView обеспечивает оперативный, дружелюбный показ ресурсов системы LynxOS, cпецифичный именно для LynxOS показ распечатки трассировки, cтатистическую оценку и графический показ работы потоков и другую полезную информацию о работе потоков.

LynxOS 5.0: операционная система для систем специального назначения

Где же в наибольшей степени будут востребованы новые возможности LynxOS 5.0 ? Конечно, в традиционных отраслях, в которых применяется LynxOS: оборонной и авиакосмической [9,10,11]. Очень показательным в этом смысле являются высказывания руководства компании GE Fanuc Intelligent Platforms (одной из ведущих в мире компаний- поставщиков аппаратных средств повышенной надежности для систем специального назначения) о том, что LynxOS 5.0 обеспечивает все необходимые функциональные возможности, которые пользуются повышенным спросом в основных военных программах (http://www.vmecritical.com/news/db/?12576). Например, в таких военных программах США и стран НАТО, как FCS (Future Combat Systems – перспективные боевые системы) и JTRS (объединенная система тактической радиосвязи). Не случайно, что LynxOS выбрана в качестве одной из базовых ОСРВ для «тяжелых» применений крупнейшими мировыми производителями аппаратных средств, таких как GE Fanuc Intelligent Platforms, Kontron AG и Curtiss-Wright Control Embedded Computing. LynxOS находит все более широкое применение и в России.
В качестве одного из конкретных примеров применения LynxOS 5.0, ориентированного на «тяжелые» применения, можно сослаться на компанию GE Fanuc Intelligent Platforms, которая выбрала LynxOS 5.0 для использования со своими наиболее современными платами VXS DSP220 и VPX DSP230, основу которых составляет многоядерный процессор Freescale MPC8641D. VPX DSP230 (рис.2) реализована инженерами GE Fanuc в перспективном конструктиве 6U VPX, поддерживает программные функции AXIS (Advanced Multiprocessor Integrated Software), что облегчает ее использование в многопроцессорных конфигурациях.

Плата VPX DSP230 компании GE Fanuc Intelligent Platforms, поставляемая с LynxOS 5.0
Рис.2 Плата VPX DSP230 компании GE Fanuc Intelligent Platforms, поставляемая с LynxOS 5.0

BSP LynxOS 5.0 для плат VXS DSP220 и VPX DSP230 было реализовано независимой компанией Pebble Bay Consulting Ltd из Англии. Эти BSP поддерживают все периферийные устройства плат VXS DSP220 и VPX DSP230, включая четыре процессора Freescale MPC8641D, восемь банков DDR2 SDRAM (в сумме дающих до 8 Гбайт памяти), Tundra Serial RapidIO для всех узлов, 8 последовательных портов, единственный XMC с поддержкой SRIO, интерфейс VME 2eSST, контроллер управления узлами и программное обеспечение для AXIS (Advanced Multiprocessor Integrated Software) компании GE Fanuc.

Заключение

Как мы видим, новая версия операционной системы LynxOS 5.0 сделала огромный шаг в направлении поддержки SMP-архитектуры. Разработчики получили адекватный продукт, соответствующий современному уровню развития многоядерных процессорных технологий. При этом разработчикам из LynuxWorks удалось сохранить преемственность с основными возможностями LynxOS, реализованными в предыдущих версиях, главными из которых является поддержка работы системы в реальном времени и совместимость с Linux на уровне двоичных файлов. Кроме этого, многие реализованные в LynxOS 5.0 методы, безусловно, будут использоваться в других продуктах LynuxWorks, таких как LynxOS-178 и LynxSecure. Нет сомнений, что новые возможности LynxOS 5.0 будут востребованы разработчиками систем специального назначения, таких как комплексы управления оружием, военная и гражданская авиация, военно-морские силы. Хотелось бы надеяться, что отечественные разработчики станут одними из первых, кто воспользуется новыми конкурентными преимуществами LynxOS 5.0.

Литература

1. Золотарев С.В., Рыбаков А.Н. Программное обеспечение многоядерных систем, Открытые системы, 2, 2006
2. Встраиваемые компьютерные технологии для сильной России, МКА: мир ВКТ, 3, 2008
3. Золотарев С.В., LynxOS-178: операционная система реального времени нового поколения для авиации, Авиакосмическое приборостростроение, 8, 2005 г.
4. Золотарев С.В., LynxSecure:время операционных систем реального времени в MILS-архитектуре пришло, Мир компьютерной автоматизации (МКА), 4, 2007 г.
5. Золотарев С.В., BlueCat Linux как программная платформа для разработки встраиваемых приложений, ChipNews, 4, 2005 г.
6. Золотарев С.В., LynxOS: Реальное время всерьез, Мир компьютерной автоматизации (МКА), 3, 2005 г.
7. Brian Goetz. Java theory and practice: Going atomic. http://www-128.ibm.com/developerworks/java/library/j-jtp11234/
8. Scott Maxwell, Linux Core Kernel Commentary (Ядро Linux в комментариях), http://www.netlib.narod.ru/library/book0010/toc.htm
9. Синенко О.В., Золотарев С.В. Современные операционные системы реального времени для перспективной авионики, Военный парад , 6(78), 2006 г.
10. Ефанов Д.В. ОС РВ LynxOS как основа современных систем ответственного применения, Автоматизация в промышленности, 2, 2008
11. Брошюра «Программное обеспечение LynuxWorks в оборонной и авиакосмической отраслях», http://www.rtsoft.ru/