Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform | страница 54
Состояние «потребителя» | Состояние «производителя» | ||
---|---|---|---|
«потребитель» блокирует мутекс | «потребитель» | READY | INTERRUPT |
«потребитель» проверяет флаг data_ready | «потребитель» | READY | INTERRUPT |
потребитель вызывает функцию pthread_sleepon_wait() | «потребитель» | READY | INTERRUPT |
функция pthread_sleepon_wait() разблокирует мутекс | мутекс свободен | READY | INTERRUPT |
функция pthread_sleepon_wait() блокируется | мутекс свободен | CONDVAR | INTERRUPT |
пауза до прерывания | мутекс свободен | CONDVAR | INTERRUPT |
аппаратные средства генерируют данные | мутекс свободен | CONDVAR | READY |
«производитель» блокирует мутекс | «производитель» | CONDVAR | READY |
«производитель» устанавливает флаг data_ready | «производитель» | CONDVAR | READY |
«производитель» вызывает pthread_sleepon_signal() | «производитель» | CONDVAR | READY |
«потребитель» «пробуждается», функция pthread_sleepon_wait() пытается заблокировать мутекс | «производитель» | MUTEX | READY |
«производитель» разблокирует мутекс | мутекс свободен | MUTEX | READY |
«потребитель» получает мутекс | «потребитель» | READY | READY |
«потребитель» обрабатывает данные | «потребитель» | READY | READY |
«производитель» ждет новых данных от аппаратуры | «потребитель» | READY | INTERRUPT |
пауза («потребитель» обрабатывает полученные данные) | «потребитель» | READY | INTERRUPT |
«потребитель» завершает обработку и разблокирует мутекс | мутекс свободен | READY | INTERRUPT |
«потребитель» возвращается в начало цикла и блокирует мутекс | «потребитель» | READY | INTERRUPT |
Последняя строка в таблице повторяет первую — мы совершили один полный цикл.
Каково назначение флага data_ready? Он служит для двух целей:
• Он является флагом состояния — посредником между «потребителем» и «производителем», указывающим на состояние системы. Если флаг установлен в состояние 1, это означает, что данные доступны для обработки; если этот флаг установлено в состояние 0, это означает, что данных нет, и поток-потребитель должен быть заблокирован.
• Он выполняет функцию «места, где происходит синхронизация со ждущей блокировкой». Более формально говоря, адрес переменной data_ready используется как уникальный идентификатор объекта, по которому осуществляется ждущая блокировка. Мы запросто могли бы применить «>(void*)12345
» вместо «>&data_ready
» — библиотеке ждущих блокировок все равно, что это за идентификатор, лишь бы он был уникален и корректно использовался. Использование же в качестве идентификатора адреса переменной есть надежный способ сгенерировать уникальный номер, поскольку не бывает же двух переменных с одинаковым адресом!
• К обсуждению различий между функциями