7.3.2 Блокировка памяти |
Предыдущая Содержание Следующая |
Одна из задержек, с которой должны иметь дело приложения реального времени, это замещение страниц (подкачка) по требованию. Приложение реального времени требует детерминированного времени отклика и подкачка является одной из основных причин неожиданных задержек при исполнении программы. Задержки из-за подкачки можно было бы избежать с помощью блокировки памяти. Предоставляются функции либо для блокировки адресного пространства программы целиком, либо для выбранной области памяти.
Функции блокировки памяти
Функции блокировки памяти приведены в Таблице 7.3. mlock запрещает замещение страниц для указанного диапазона памяти, а mlockall запрещает замещение для всех страниц, которые связаны с адресным пространством процесса. Это включает в себя страницы кода, данных, стека, разделяемых библиотек, общей памяти и отображённых на память файлов. Использование этих функций иллюстрирует Распечатка 7.3. Эти функции должны вызываться с привилегией суперпользователя.
Таблица 7.3 Функции блокировки памяти POSIX.1b
Приложение с требованиями реального времени как правило многопоточное, некоторые потоки которого работают режиме реального времени, а некоторые не в режиме реального времени. Для таких приложений mlockall использоваться не должна, поскольку это также блокирует память потоков, не работающих в режиме реального времени. В следующих двух разделах мы обсудим два подхода к компоновке для выполнения селективной блокировки памяти в таких приложениях.
Эффективная блокировка с помощью сценария компоновщика
Идея заключается в размещении объектных файлов, содержащих код и данные реального времени, в отдельном разделе компоновщика с помощью сценария компоновщика. Блокирование с помощью mlock такого раздела во время запуска программы привело бы к блокировка только кода и данных, использующихся в режиме реального времени. Для иллюстрации этого возьмём пример приложения. В Распечатке 7.4 мы предполагаем, что hello_rt_world - это функция реального времени, которая работает с rt_data в rt_bss как неинициализированными данными. Для достижения селективного блокирования должны быть выполнены следующие шаги:
Вы можете проверить, что все функции и данные реального времени находятся в соответствующих разделах с помощью команды objdump, как показано ниже.
# objdump -t hello ..... 08049720 g .rt_bss 00000000 __start_rt_bss 08049760 g O .rt_bss 00000064 rt_bss 080497c4 g .rt_bss 00000000 __end_rt_bss..... 080482f4 g .rt_text 00000000 __start_rt_text 080482f4 g F .rt_text 0000001d hello_rt_world 0804834a g .rt_text 00000000 __end_rt_text ...... 080496c0 g .rt_data 00000000 __start_rt_data 080496c0 g O .rt_data 00000011 rt_data 08049707 g .rt_data 00000000 __end_rt_data
Эффективная блокировка с помощью раздела атрибутов GCC
Этот подход может быть использован, если трудно поместить код режима реального времени и код, не работающий в реальном времени, в отдельные файлы. При таком подходе, чтобы разместить наш код и данные реального времени в соответствующих разделах, мы используем раздел атрибутов GCC. Наконец, наша цель достигается блокировкой только этих разделов. Этот подход является очень гибким и простым в использовании. Распечатка 7.6 показывает Распечатку 7.4, переписанную, чтобы попасть в эту категорию. Вы можете проверить, что все функции и данные реального времени находятся в соответствующих разделах с помощью команды objdump, как показано ниже.
# gcc -o hello hello.c # objdump -t hello ..... ..... 08049724 g *ABS* 00000000 __stop_real_bss 08048560 g *ABS* 00000000 __stop_real_text 080496a0 g *ABS* 00000000 __start_real_data 080496b1 g *ABS* 00000000 __stop_real_data 080496c0 g *ABS* 00000000 __start_real_bss 0804852c g *ABS* 00000000 __start_real_text 080496c0 g O real_bss 00000064 rt_bss 080496a0 g O real_data 00000011 rt_data 0804852c g F real_text 00000034 hello_rt_world ...... ......
Обратите внимание на определённые компоновщиком символы __start_real_text, __stop_real_text, и так далее.
Что следует помнить
▪Один вызов munlock или munlockall разблокирует область памяти, даже если она заблокирована процессом несколько раз. ▪Страницы, отображённые в несколько областей памяти или используемые несколькими процессами, будут заблокированы в памяти до тех пор, пока они заблокированы по крайней мере одним процессом или в одной области памяти. ▪Дочерние процессы не наследуют блокировки страниц через ветвление. ▪Страницы, заблокированные mlock или mlockall, гарантированно остаются в памяти, пока страницы не разблокированы munlock или munlockall, не отключено их отображение через munmap, или пока процесс не завершится или не запустит другую программу с помощью exec. ▪Лучше делать блокировку памяти при инициализации программы. Все динамические выделения памяти, создание совместно используемой памяти и отображение файлов должно быть сделано при инициализации с последующей блокировкой их mlock. ▪В случае, если вы хотите быть уверенными, что выделения памяти для стека остаются детерминированными, вам также необходимо заблокировать некоторые страницы стека. Чтобы избежать замещения для сегмента стека, вы можете написать небольшую функцию lock_stack и вызвать её во время инициализации. ▪Будьте великодушны к другим процессам, работающим в вашей системе. Агрессивная блокировка может забрать ресурсы других процессов.
| |||||||||||
Предыдущая Содержание Следующая |