- •Національний авіаційний університет
- •Лабораторний практикум з дисципліни «Мультиплатформені операційні середовища»
- •Визначення, позначення і скорочення
- •2.2. Використання клавіатури пк в ос qnx
- •2.3. Основні команди в ос qnx
- •2.4. Робота в файловій системі ос qnx
- •2.5. Ініціювання і завершення роботи в графічній оболонці Photon
- •3. Зміст звіту про лабораторну роботу
- •4. Питання для самоконтролю
- •5. Завдання на лабораторну роботу
- •Лабораторна робота № 2. Компіляція програм Короткі теоретичні відомості
- •Мікроядро
- •Системні і користувацькі процеси
- •Драйвери пристроїв
- •Зв'язок між процесами (ipc)
- •Qnx як мережа
- •Текст програми
- •Лабораторна робота №4. Повідомлення Короткі теоретичні відомості Архітектура і структура обміну повідомленнями
- •Текст програми
- •Послідовність дій
- •Результати
- •Лабораторна робота № 5. Тайм-аути Короткі теоретичні відомості Тайм-аути ядра
- •Текст програми
- •Текст програми
- •Послідовність дій
- •Результати
- •Послідовність дій
- •Результати
- •Лабораторна робота № 8. Створення найпростішого сервера в ос qnx
- •Короткі теоретичні відомості Функція Socket
- •Функція Bind
- •Функції listen і accept
- •Читання з сокета
- •Запис в сокет
- •Закриття сокета
Текст програми
#include <stdio.h>
#include <time.h>
#include <sync.h>
#include <sys/neutrino.h>
barrier_t barrier;
//int data_ready = 0;
//int inf = 0;
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
void *thread1 (void * not_used)
{
time_t now;
char buf[27];
time(&now);
printf("Potok 1, vremia starta %s \n", ctime_r(&now,buf));
sleep(3);
barrier_wait(&barrier);
time(&now);
printf("barier v potoke 1 , vremia srabativania %s \n", ctime_r(&now,buf));
}
void *thread2 (void * not_used)
{
time_t now;
char buf[27];
time(&now);
printf("Potok 2, vremia starta %s \n", ctime_r(&now,buf));
sleep(6);
barrier_wait(&barrier);
time(&now);
printf("barier v potoke 2 , vremia srabativania %s \n", ctime_r(&now,buf));
}
main()
{
time_t now;
char buf[27];
barrier_init(&barrier, NULL, 3);
printf("Start \n");
pthread_create(NULL,NULL, thread1 ,NULL);
pthread_create(NULL,NULL, thread2 ,NULL);
time(&now);
printf(" Main(): oshidanie y bariera, vremia %s \n", ctime_r(&now,buf));
barrier_wait(&barrier);
time(&now);
printf("barier v main() , vremia srabativania %s \n", ctime_r(&now,buf));
sleep(5);
}
Послідовність дій
Основний потік створив об'єкт типу «бар'єр» і ініціалізув його значенням лічильника, рівним числу потоків (включаючи себе!), Які повинні «зустрітися» у бар'єра, перш ніж він «прорветься». У нашому прикладі цей індекс дорівнював 3 - один для потоку main(), один для потоку thread1() і один для потоку thread2(). Потім, як і колись, стартують потоки обчислення графіки (у нашому випадку це потоки thread1() і thread2()). Для прикладу замість приведення реальних алгоритмів графічних обчислень ми просто тимчасово «приспали» потоки, вказавши в них sleep (20) і sleep (40), щоб імітувати обчислення. Для здійснення синхронізації основний потік (mаin ()) просто блокує сам себе на бар'єрі, знаючи, що бар'єр буде розблоковано тільки після того, як робочі потоки аналогічно приєднаються до нього.
Як згадувалося раніше, з функцією pthreadJoin() робочі потоки для синхронізації головного потоку з ними повинні померти. У випадку ж з бар'єром потоки живуть і відчувають себе цілком добре. Фактично, відпрацювавши, вони просто розблокуються по функції barrier_wait(). Тонкість тут у тому, що ви зобов'язані передбачити, що ці потоки повинні робити далі! У нашому прикладі з графікою ми не дали їм ніякого завдання для них - просто тому що ми так придумали алгоритм. У реальному житті ви могли б захотіти, наприклад, продовжити обчислення.
Результати
# Root / a.out
Start
Potok 1, vremia starta Tue Oct 21 00:29:01 2003
Potok 2, vremia starta Tue Oct 21 00:29:01 2003
Main (): oshidanie y bariera, vremia Tue Oct 21 00:29:01 2003
barier v potoke 2, vremia srabativania Tue Oct 21 00:29:07 2003
barier v main (), vremia srabativania Tue Oct 21 00:29:07 2003
barier v potoke 1, vremia srabativania Tue Oct 21 00:29:07 2003
# / **
Лабораторна робота № 7. Синхронізація процесів. Умовні змінні
Короткі теоретичні відомості
Умовні змінні
Умовні змінні (або «condvars») дуже схожі на очікуючі блокування, які ми розглядали вище. Насправді, очікуючі блокування - це надбудова над механізмом умовних змінних, і саме тому у нас зустрічається стан CONDVAR. Функція pthread_cond_wait() точно так же звільняє мутекс, чекає, а потім повторно блокує мутекс, аналогічно функції pthread_sleepon_wait().
Текст програми
#include <stdio.h>
#include <pthread.h>
int data_ready = 0;
int inf = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
void *consumer (void * notused)
{
printf("Eto potrebitel \n");
while(1)
{
pthread_mutex_lock (&mutex);
printf("W1 \n");
while (!data_ready)
{
printf("W2 \n");
pthread_cond_wait (&condvar, & mutex);
printf("W3 \n");
}
printf("dannie ot proizv = %d \n",inf);
data_ready=0;
pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);
}
}
void *producer (void * notused)
{
printf("Eto ptoizvoditel \n");
while(1)
{
sleep(2);
printf("ptoizvoditel polychil dannie ot h/w = %d \n",inf);
pthread_mutex_lock (&mutex);
printf("Wp1 \n");
while (data_ready)
{
printf("Wp2 \n");
pthread_cond_wait (&condvar, & mutex);
}
data_ready=1;
inf++;
printf("Wp3 \n");
pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);
}
}
main()
{
printf("Start \n");
pthread_create(NULL,NULL, consumer,NULL);
pthread_create(NULL,NULL, producer,NULL);
sleep(10);
}
