Вы находитесь на странице: 1из 17

Контакты

Сидельников Виктор Викторович vvs_home@list.ru

Программное обеспечение
QNX – Real-Time OS
http://www.qnx.com/products/evaluation
Other license keys Academic -> Single user license

QNX® Software Development Platform 6.6.0 – Windows Hosts


QNX SDP 6.6.0 runtime ISO for VMware [or virtual machine]

Литература
Цилюрик О., Горшко Е. Анатомия параллелизма QNX/UNIX
Кертен Р. Введение в QNX Neutrino 2. Руководство для разработчиков
приложений реального времени

Семафоры, условные переменные 2016 v.01 1


Средства разработки

Инструментальная ВМ Целевая платформа


(Development host) (Target system)

Средства разработки QNX Neutrino RTOS,


(QNX Momentics ID, C, C++, драйверы,
библиотеки, документация ) приложение

Лабораторная ВМ

QNX Momentics ID VMware player


QNX Neutrino
C, C++, библиотеки, RTOS,
документация приложение

Семафоры, условные переменные 2016 v.01 2


Задание

1. Построить «лабораторную машину» (см. A_Quickstart_Guide.pdf)


- получить лицензию и скачать дистрибутивы QNX
а) QNX Momentix IDE
б) дистрибутив ядра для виртуальной машины
- установить IDE
- скачать и установить виртуальную машину (VMware)
- установить ядро QNX

2. Реализовать задачу «Поставщик – Потребитель»

Семафоры, условнык переменные 2016 v.01 3


«Поставщик-Потребитель»

Поставщик A Потребитель

Две процесса (две нитки) работают с некоторым Буфером A.


Процесс «Поставщик» в случайные моменты времени записывает
в Буфер A «пакеты информации», процесс «Потребитель»
считывает информацию из Буфера A. Построить модель работы
«Поставщика» и «Потребителя» при следующих условиях:
1. «Поставщик» не может записывать информацию и
блокируется, если Буфер A полон.
2. «Потребитель» Блокируется, если Буфер A пуст.
3. Не допускается одновременная запись и чтение информации.

Задание следует реализовать двумя способами:


а) с использованием трех семафоров
б) с использованием условной переменной

Семафоры, условные переменные 2016 v.01 4


Функции для работы с нитями

#include <pthread.h>
int pthread_create( pthread_t* thread, const pthread_attr_t* attr,
void* (*start_routine)(void* ), void* arg );
thread – идентификатор нити (ID), устанавливается при создании;
attr – атрибутная запись, при значении NULL устанавливается по умолчанию;
void* (*start_routine)(void* ) – функция, код которой выполняется в потоке;
arg – аргумент, передаваемый в функцию потока
Простой вызов - pthread_create(&t, NULL, &func, NULL)

pthread_t pthread_self( void ); - возвращает ID потока;

int pthread_join( pthread_t thread, void** value_ptr );


thread – ID нити, окончание которой оидается
value_ptr – NULL или указатель на область, куда будет помещено значение,
передаваемое в pthread_exit завершенной нитью
pthread_join( t, NULL);

#include <unistd.h>
unsigned int sleep( unsigned int seconds );

Семафоры, условные переменные 2016 v.02 5


Создание нити,
синхронизация завершения
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* test_t(void* arg) {


printf("Thread %d started \n", pthread_self());
int i;
for(i=0; i<=10; i++) {
printf("Thread %d is working %d\n", pthread_self(), i);
sleep(1);
}
printf("Thread %d stop\n”, pthread_self());
return EXIT_SUCCESS;
}

int main(int argc, char *argv[]) {


pthread_t thread_id;
pthread_create(&thread_id, NULL, &test_t, NULL);
printf("Main thread stop\n");
pthread_join(thread_id, NULL);
return EXIT_SUCCESS;
}

Семафоры, условные переменные 2016 v.01 6


Семафоры, мьютексы, условные
переменные

#include <semaphore.h>
int sem_init( sem_t * sem, int pshared, unsigned value );
int sem_wait( sem_t * sem );
int sem_post( sem_t * sem );

#include <pthread.h>
int pthread_mutex_init( pthread_mutex_t* mutex, const pthread_mutexattr_t* attr );
int pthread_mutex_lock( pthread_mutex_t* mutex );
int pthread_mutex_unlock( pthread_mutex_t* mutex );

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


int pthread_cond_init( pthread_cond_t* cond, pthread_condattr_t* attr );
int pthread_cond_wait( pthread_cond_t* cond, pthread_mutex_t* mutex );
int pthread_cond_signal( pthread_cond_t* cond );
int pthread_cond_broadcast( pthread_cond_t* cond );

7
Семафоры, условные переменные 2016 v.03
Вызовы функций семафора
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>

void f(pthread_t id) {


printf("Thread %d called this function\n", id);
}
int main(int argc, char *argv[]) {
sem_t s; pthread_t thr_2;
sem_init(&s, NULL, 10);
void* thread_2(void* arg) { pthread_t id = pthread_self();
pthread_t id = pthread_self(); pthread_create(&thr_2, NULL, &thread_2, NULL);
for(;;) { for(;;) {
printf("Tread %d is working\n", id ); printf("Tread %d is working\n", id );
sem_wait(&s); sem_wait(&s);
f(id); f(id);
sem_post(&s); sem_post(&s);
usleep(300); usleep(300);
} }
return 0; printf("Main thread stop\n");
} pthread_join(thr_2, NULL);
return EXIT_SUCCESS;
}

8
Семафоры, условные переменные 2016 v.01
Вызовы функций мьютекса
#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex
int count = 0;

void* thr_1( void* arg ) void* thr_2( void* arg )


{ {
int tmp = 0; int tmp = 0;
while( 1 ) { while( 1 ) {
pthread_mutex_lock( &mutex ); pthread_mutex_lock( &mutex );
tmp = count++; tmp = count--;
pthread_mutex_unlock( &mutex ); pthread_mutex_unlock( &mutex );
printf( "Count is %d\n", tmp ); printf( "** Count is %d\n", tmp );
sleep( 1 ); sleep( 2 );
} }
return 0; return 0;
} }
int main( void )
{
pthread_create( NULL, NULL, &thr_1, NULL );
pthread_create( NULL, NULL, &thr_2, NULL );
sleep( 10 );
return 0;
}

9
Семафоры, условные переменные 2016 v.01
Использование условных переменных
pthread_cond_t cond;
pthread_mutex_t mutex;
bool c;

void* thread_1 (void* args){


while(1){
pthread_mutex_lock(&mutex);
if (c)
pthread_cond_wait(&cond, &mutex);
Do_Action_1; // c устанавливается в false
pthread_mutex_unlock(&mutex);
sleep(sec_1)
};
return EXIT_SUCCESS;
}

void* thread_2 (void* args){


while(1){
pthread_mutex_lock(&mutex);
Do_Action_2; // c устанавливается в true
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex); int main() {
sleep (sec_2); pthread_t thr_1, thr_2;
}; pthread_cond_init(&cond, NULL);
return EXIT_SUCCESS; pthread_mutex_init(&mutex, NULL);
} pthread_create(&thr_1, NULL, &thread_1, NULL);
pthread_create(&thr_2, NULL, &thread_2, NULL);
pthread_join(thr_1, NULL);
pthread_join(thr_2, NULL);
return EXIT_SUCCESS;
}

10
Семафоры, условные переменные 2019 v.01
0 condition_1 = false thr_1 thr_2
. . .
// Thread_1, thr_1
1 pthread_mutex_lock(&mutex); 1 Захват мьютекса
if (c) 6 Блокировка на
2 pthread_cond_wait(&cond, &mutex); мьютексе
3 Do_Action_1; // c = false Блокировка
5 pthread_mutex_unlock(&mutex);
2 Блокировка на УП, 6 Разблокировка,
освобождение захват мьютекса
мьютекса

// Thread_2, thr_2 7 Do_Action_2


Блокировка
6 pthread_mutex_lock(&mutex);
7 Do_Action_2; // c = true 8 Сигнал
8 pthread_cond_signal(&cond);
9 pthread_mutex_unlock(&mutex); 3 Do_Action_1 9 Возврат мьютекса
владельцу

5 Освобождение мьютекса

11
Семафоры, условные переменные 2019 v.01
Монитор Хоара
Хоар Чарлз Энтони Ричард 1934
C.A.R. Hoare Monitors: An Operating System Structuring Concept
http://people.cs.uchicago.edu/~shanlu/teaching/33100_fa15/papers/hoare-
monitors.pdf.

monitor имя_монитора;
декларация данных, локальных для монитора;
procedure имя_процедуры (формальные параметры);
begin тело процедуры end;
Декларация других процедур;
begin
Инициализация локальных данных;
еnd.

12. Мьютекс, монитор , условная переменная 2018 v.01 12


monitor Буфер;
СамБуфер array[1..ДлинаБуфера]: Данное; Пример
СчетчикЗаписей : integer;

procedure Записать(d : Данное);


begin
Поставщик:
...
loop
end;
D = Производство;
Буфер.Записать(D);
function Прочитать : Данное;
endloop;
begin
...
Потребитель:
end;
loop
D = Буфер.Прочитать;
begin
Обработка(D);
СчетчикЗаписей = 0;
endloop;
end Буфер.
Parbegin Поставщик; Потребитель;
Parend;

12. Синхронизация_потоков_QNX 2015 v.01 13


Процедура доступа
• Обеспечивается взаимное исключение доступа к ресурсам, описанным в
мониторе (Буфер.Записать(D) и Буфер.Прочитать()- не могут
выполняться одновременно)

• Управление ОчередьДоступа (например, FIFO) обеспечивает


очередность доступа процессов к монитору

Поставщик
Буфер
Записать(D)
procedure Записать

Потребитель function Прочитать

D:=Прочитать ОчередьДоступа

12. Мьютекс, монитор , условная переменная 2018 v.01 14


Монитор и условная переменная

Тип данных: condition

Операции над условной переменной:


cond : condition;
wait(cond):
поставить активный процесс в очередь, связанную переменной cond
signal(cond):
первый процесс из очереди cond активизируется («семантика Хоара»)
или ставится в очередь готовых («семантика Меса»);
check(cond):integer:
возвращает кол-во процессов, ждущих в очереди cond

12. Мьютекс, монитор , условная переменная 2018 v.01 15


Пример

monitor Буфер;
СамБуфер array[1..ДлинаБуфера] : Данное;
СчетчикЗаписей : integer;
НеПуст, НеПолон : condition;

procedure Записать(d : Данное);


begin
if (СчетчикЗаписей >= ДлинаБуфера) then
wait(НеПолон);
Записать_в_буфер;
СчетчикЗаписей = СчетчикЗаписей + 1;
signal(НеПуст);
end;

12. Мьютекс, монитор , условная переменная 2018 v.01 16


Пример

function Прочитать : Данное;


begin
if (СчетчикЗаписей == 0) then
wait(НеПуст);
Прочитать_из_буфера;
СчетчикЗаписей = СчетчикЗаписей – 1;
signal(НеПолон);
end;

begin
СчетчикЗаписей = 0;
endБуфер;

12. Мьютекс, монитор , условная переменная 2018 v.01 17

Вам также может понравиться