Под контролируемым выполнением [1, 2] понимается специально организованный процесс функционирования аппаратно-программной системы, цель которого – выполнение системой своих задач несмотря на наличие ошибок, атак и отказов.
Основные положения концепции контролируемого выполнения:
– интеграция средств информационной безопасности, отладки и управления [3];
– распространение контролируемого выполнения на все этапы жизненного цикла системы;
– целостность набора средств контролируемого выполнения, различающихся по степени воздействия на целевую систему, возможность взаимодействия между этими средствами.
Частными случаями контролируемого выполнения являются применение средств управления информационными системами, интерактивная отладка [4], мониторинг систем, их самоконтроль [5], воспроизведение предыдущих сеансов работы систем [6], моделирование, сбор и анализ количественных характеристик их функционирования [7], самолечение систем [8, 9].
В данной работе в контексте контролируемого выполнения авторами предложена методика самолечения POSIX-систем, основанная на использовании механизма трассировки. Самолечение подразумевает способность системы находить, исследовать ошибки в работе и реагировать на них. Компоненты или системы, обладающие самолечением, должны уметь исследовать системные ошибки и, учитывая наложенные извне ограничения, вносить подходящие исправления. Для автоматического нахождения системных ошибок или возможных будущих ошибок необходимо знать ожидаемое поведение системы. Автономные системы должны иметь знание о своем поведении и способность оценивать его корректность в данной ситуации.
Трассировка в POSIX-системах
В 2001 году департамент стандартов IEEE включил в очередную редакцию POSIX рекомендации по трассировке программно реализуемых процессов с целью унификации интерфейса средств сбора и анализа данных об их выполне- нии [10].
Стандарт фиксирует минимальную функциональность средств трассировки, которые должна предоставлять POSIX-совместимая операционная система. В стандарте POSIX-2001 под трассировкой понимаются порождение, накопление и анализ данных о событиях, имевших место при выполнении пользовательского приложения.
В трактовке стандарта POSIX-2001 в трассировке логически участвуют три процесса, которые физически могут совпадать между собой: трассируемый (целевой), трассирующий (управляющий трассировкой) и анализирующий данные трассировки.
Сведения о действиях, производимых при выполнении приложения, фиксируются в виде объектов данных, называемых событиями трассировки (или просто событиями). События и данные, необходимые для их интерпретации, записываются в потоки трассировки.
Трассируемый процесс должен быть специальным образом организован: реализующая его программа должна содержать точки трассировки – действия, способные генерировать события трассировки. Для каждого трассируемого процесса должен быть открыт по крайней мере один поток трассировки. Процесс, создавший поток трассировки, называется трассирующим (управляющим трассировкой). Анализирующим называется процесс, извлекающий события трассировки из общего потока с целью получения информации о поведении трассируемого приложения.
События трассировки подразделяются на пользовательские и системные.
Пользовательские события порождаются при вызове функции posix_trace_event(). Системные события генерируются в ответ на действия приложения или ОС. Стандартом предусмотрен механизм фильтрации, позволяющий отменять генерацию событий определенных типов, сокращая таким образом объем трассировочных данных.
Одно из главных требований к системе трассировки – минимизация накладных расходов. Исходя из этого, потоки трассировки, как правило, хранят в оперативной памяти. Для получения стабильной копии потока с целью последующего анализа стандарт пре- дусматривает его сохранение в журнале трассировки в долговременной памяти. И для потоков, и для журналов трассировки правила обработки ситуации заполнения могут сводиться к записи новых событий поверх самых старых или к приостановке трассировки. Для потоков возможен сброс в журнал с последующей очисткой, а для журналов – потенциально неограниченное расширение.
Стандарт определяет два способа анализа трассы: в ходе сбора событий (online analysis) и после сбора событий (offline analysis). В первом случае анализирующий процесс читает данные из потока событий, во втором – из журнала. Оба способа представлены на рисунках 1 и 2 соответственно.
Программный интерфейс трассировки POSIX должен предоставлять следующие возможности:
– параллельная трассировка системных и пользовательских событий;
– трассировка события, относящегося к конкретному процессу, а также системных событий, не относящихся к какому-либо процессу;
– управление трассировкой некоторого процесса как потоками управления этого процесса, так и внешними процессами;
– управление трассировкой некоторого потока управления другими потоками управления данного процесса.
И он должен удовлетворять ряду требований:
– одновременно может осуществляться трассировка только одного процесса, при этом необходимо запретить трассировку сущностей, больших, чем процесс, например группы процессов;
– каждый вновь порождаемый поток трассируемого процесса по умолчанию тоже является трассируемым;
– независимо разрабатываемый код может подвергаться трассировке без дополнительных настроек и без конфликтов;
– для доступа к потоку событий должен использоваться стандартный интерфейс прикладного программирования;
– формат потока и журнала трассировки не определяется;
– должна быть возможность поддержки нескольких потоков трассировки в системе.
Всю необходимую дополнительную информацию можно получить из [2].
Отметим несколько слабых мест этого стандарта. Во-первых, нет возможности отлаживать группы процессов, что уже является серьезным ограничением для применения POSIX-2001 при мониторинге состояния распределенных приложений. Во-вторых, не отражен механизм группирования потоков управления внутри одного процесса (и вообще минимальной единицей применения трассировки является именно процесс, а не отдельный поток). В-третьих, не прописаны механизмы и интерфейсы для группировки событий (есть только две группы – пользовательские события и системные).
Тем не менее при разработке средств мониторинга и самолечения целесообразно использовать интерфейс POSIX-2001 в качестве базового с последующим его расширением.
Реализация механизма самолечения в POSIX-системах
Для начала введем еще одно понятие. Система называется самостабилизирующейся, если из любой конфигурации она за конечное время приходит в безопасную конфигурацию, а из безопасной всегда переходит в безопасную.
Аппаратно-программная система будет самостабилизирующейся, если этим свойством обладают аппаратура, операционная система и программные приложения. Далее предлагается методика реализации самостабилизирующейся программной системы, основанная на анализе потока событий специально выделенным управляющим потоком.
Итак, для реализации механизма самостабилизации (самолечения) разработчик программной системы должен описать так называемые сигнатуры правильного поведения системы. Это последовательности пользовательских и системных событий, выполнение которых говорит о корректной реализации системы. Соответственно, система должна быть надлежащим образом настроена, то есть в критические участки кода разработчик должен добавить вызовы функции генерации пользовательских событий, а также включить протоколирование необходимых системных событий.
Кроме того, при разработке системы необходимо зарезервировать определенные ресурсы (время выполнения и память) для отдельного потока управления или процесса, который будет выполнять функции монитора здоровья целевой системы. Монитор здоровья следит за соответствием возникающих событий сигнатурам правильного поведения системы и в случае обнаруженного расхождения производит действия по стабилизации системы. В простейшем случае – перезапуск нескольких (или всех) потоков управления или процессов.
Для примера рассмотрим POSIX-процесс, содержащий три потока. Два из них – это сервер и клиент, связанные по UDP-протоколу, третий контролирует происходящее в них через проверку событий, генерируемых этими потоками, и при необходимости перезапускает сервер и клиента. Клиент и сервер обмениваются сообщениями, а при получении и отправке фиксируют это в протоколе трассировки. Использование UDP-протокола обеспечивает необходимую скорость работы системы, но не дает гарантии успешной доставки всех сообщений.
Для реализации механизма самостабилизации в данной системе контролирующий поток проверяет приходящие в протокол события и при несоответствии сигнатуре корректного поведения системы осуществляет ее перезапуск.
Код сервера:
while (1){
sleep(10); /* Искусственная задержка */
bytesRead = recvfrom(sock, recvData, 1024, 0, (struct sockaddr *)&clientAddr, &addrLen); /* Попытка получить сообщение */
if(bytesRead == -1){
printf("Server receving error!!!\n");
close(sock);
return 7;
}
recvData[bytesRead] = '\0';
posix_trace_event(serverRecEvent, recvData, strlen(recvData)); /* Отсылка в протокол информации о том, что сервер успешно получил информацию */
posix_trace_event(serverSendEvent, answer, strlen(answer)); /* Отправка в протокол информации о посылке сообщения */
outCode = sendto(sock, answer, strlen(answer), 0, (struct sockaddr *)&clientAddr, sizeof(struct sockaddr)); /*Попытка отправить сообщение */
if(outCode == -1){
printf("Server sending error!!!\n");
close(sock);
return 8;
}
sched_yield();
}
Код клиента аналогичен и вначале отправляет сообщение, а потом пытается получить ответ от сервера.
Контролирующий поток создает потоки клиента и сервера, затем начинает обработку приходящих событий:
while (limit > 0){
curTime = time (NULL);
const struct timespec timeout = {curTime, 500000};
if(posix_trace_timedgetnext_event(testTrace, &event, recvData, 1024, &bytesRead, &outCode, &timeout)!= 0 || outCode != 0){ /*Попытка взять следующее событие из протокола */
printf("Can't read events!!!\n");
return 5;
}
if(event.posix_event_id == clientSendEvent && state == 0){
printf("Client sent message\n");
state++; /*Состояние, показывающее, какое событие ожидается дальше */
importantTime = time (NULL); /*Время с прошлого получения ожидаемого события */
}
else if(event.posix_event_id == serverRecEvent && state == 1){
printf("Server received message\n");
state++;
importantTime = time (NULL);
}
else if(event.posix_event_id == serverSendEvent && state == 2){
printf("Server sent message\n");
state++;
importantTime = time (NULL);
}
else if(event.posix_event_id == clientRecEvent && state == 3){
printf("Client received message\n");
state = 0;
importantTime = time (NULL);
}
curTime = time(NULL);
dif = difftime(curTime, importantTime);
if(dif > 15){ /*Если ожидаемое событие не было получено в течение 15 секунд, рестарт системы */
printf("Restarting system\n");
outCode = pthread_create(&clientThread, &attributes, client, 0);
if(0 != outCode){
printf("Can't create new client thread!!! Error code : %d\n", outCode);
return 6;
}
outCode = pthread_create(&serverThread, &attributes, server, 0);
if(0 != outCode){
printf("Can't create new server thread!!! Error code : %d\n", outCode);
return 7;
}
importantTime = time(NULL);
state = 0;
limit --;
}
sched_yield();
}
В заключение отметим, что разработанная авторами концепция контролируемого выполнения направлена на то, чтобы обеспечить выполнение системой своей миссии несмотря на внутренние ошибки и внешние случайные или умышленные деструктивные воздействия.
Контролируемое выполнение включает в себя широкий спектр механизмов информационно-управляющего воздействия, среди которых ключевая роль отводится средствам самоконтроля аппаратуры и программ, а также средствам самолечения.
Базой для выполнения технологических требований к средствам контролируемого выполнения служат использование стандартов и архитектурных подходов, разработанных для средств управления, интеграция средств информационной безопасности, отладки и управления.
Конфигурация системы является безопасной, если система демонстрирует поведение, соответствующее предварительно сформулированным требованиям.
В данной работе в контексте контролируемого выполнения авторами был исследован механизм трассировки POSIX-систем и предложена методика самолечения (самостабилизации) аппаратно-программных систем.
Литература
1. Бетелин В.Б., Галатенко В.А., Костюхин К.А. Основные понятия контролируемого выполнения сложных систем // Прилож. к журн. «Информационные технологии». 2013. № 3. 32 с.
2. Галатенко В.А., Костюхин К.А. Отладка и мониторинг распределенных разнородных систем // Информационная безопасность. Инструментальные средства программирования. Базы данных; [под ред. В.Б. Бетелина]. М.: Изд-во НИИСИ РАН, 2001. С. 27–48.
3. Jackson D. A Direct Path to Dependable Software. Communications of the ACM, vol. 52, April, 2009, pp. 78–88.
4. Тэллес М., Хсих Ю. Наука отладки. М.: КУДИЦ-ОБРАЗ, 2003.
5. Andersson J., de Lemos R., Malek S., Weyns D. Reflecting on Self-Adaptive Software Systems. Proc. Intern. Conf. SEAMS'09. 2009, pp. 38–47.
6. Andrzejak A. Generic Self-Healing via Rejuvenation: Challenges, Status Quo and Solutions. Proc. 4th IEEE Intern. Conf. on Self-Adaptive and Self-Organazing Systems Workshop, 2010, pp. 239–242.
7. Khalid A., Haye M.A., Khan M.J., Shamail S. Survey of Frameworks, Architectures and Techniques in Autonomic Computing. Proc. 5th Intern. Conf. on Autonomic and Autonomous Systems. 2009, pp. 220–225.
8. Jung G., Margaria T., Wagner C., Bakera M. Formalizing a Methodology for Design- and Runtime Self-Healing. Proc. 7th IEEE Intern. Conf. and Workshop on Engineering of Autonomic and Autonomous Systems. 2010, pp. 106–115.
9. Michiels S., Desmet L., Joosen W., Verbaeten P. The DiPS+ Software Architecture for Self-healing Protocol Stacks. Proc. 4th Working IEEE/IFIP Conf. on Software Architecture (WICSA'04). 2004, pp. 233–242.
10. The Open Group Base Specifications. IEEE Std 1003.1, 2001, iss. 6.
References
1. Betelin V.B., Galatenko V.A., Kostyukhin K.A. The main concepts of the complex systems controlled
execution paradigm. Informatsionnye tekhnologii [Information Technologies]. Additional issue, no. 3, 2013 (in Russ.).
2. Galatenko V.A., Kostyukhin K.A. Debugging and monitoring of distributed heterogeneous systems.
Informatsionnaya bezopasnost. Instrumentalnye sredstva programmirovaniya. Bazy dannykh [Information Security.
Software Programming Tools. Databases]. Moscow, SRISA RAS Publ., 2001, pp. 27 –48 (in Russ.).
3. Jackson D. A direct path to dependable software. Communications of the ACM. 2009, vol. 52, pp. 78–88.
4. Telles M., Hsieh Y. The Science of Debugging. Scottsdale AZ, USA, Coriolis Group Books, 2001.
5. Andersson J., de Lemos R., Malek S., Weyns D. Reflecting on self-adaptive software systems. Proc.
SEAMS'09. 2009, pp. 38–47.
6. Andrzejak A. Generic Self-Healing via Rejuvenation: Challenges, Status Quo and Solutions. Proc. 4th IEEE
Int. Conf. on Self-Adaptive and Self-Organazing Systems Workshop. 2010, pp. 239–242.
7. Khalid A., Haye M.A., Khan M.J., Shamail S. Survey of Frameworks, Architectures and Techniques in
Autonomic Computing. Proc. 5th Int. Conf. On Autonomic and Autonomous Systems. 2009, pp. 220–225.
8. Jung G., Margaria T., Wagner C., Bakera M. Formalizing a Methodology for Design- and Runtime Self-Healing. Proc. 7th IEEE Int. Conf. and Workshop on Engineering of Autonomic and Autonomous Systems. 2010,
pp. 106–115.
9. Michiels S., Desmet L., Joosen W., Verbaeten P. The DiPS+ Software Architecture for Self -healing Protocol
Stacks. Proc. 4th Working IEEE/IFIP Conf. on Software Architecture (WICSA'04). 2004, pp. 233–242.
10. The Open Group Base Specifications. Iss. 6. IEEE Std 1003.1, 2001.