Тайм-ауты ядра при обмене сообщениями — КиберПедия 

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...

Тайм-ауты ядра при обмене сообщениями

2021-05-27 33
Тайм-ауты ядра при обмене сообщениями 0.00 из 5.00 0 оценок
Заказать работу

 

Все становятся несколько сложнее, когда вы используете тайм- ауты ядра при обмене сообщениями. На момент отправки клиентом сообщения сервер может как ожидать его, так и нет. Это означает, что клиент может заблокироваться как по передаче (если сервер еще не принял сообщение), так и по ответу (если сервер принял сообщение, но еще не ответил). Основной смысл здесь в том, что вы должны предусмотреть оба блокирующих состояния в параметре flafs функции TimerTimeout(), потому что клиент может оказаться в любом из них.

Чтобы задать несколько состояний, сложите их операцией ИЛИ (OR): TimerTimeout (_NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY).

Это вызовет тайм-аут всякий раз, когда ядро переведет клиента в состояние блокировки по передаче (SEND) или по ответу (REPLY). В тайм-ауте SEND-блокировки нет ничего особенного — сервер еще не принял сообщение, значит, ничего для этого клиента он не делает. Это значит, что если ядро генерирует тайм-аут для SEND-блокированного клиента, сервер об этом информировать не обязательно. Функция MsgSendQ клиента возвратит признак ETIMEDOUT и обработка тайм-аута завершится.

Однако, если сервер уже принял сообщение клиента, и клиент желает разблокироваться, для сервера существует два варианта реакции. Если сервер не указал флаг _NTO_CHF_UNBLOCK на канале, по которому было принято сообщение, клиент будет разблокирован немедленно, и сервер не получит об этом никакого оповещения. У большинства серверов, флаг _NTO_CHF_UNBLIOCK всегда установлен. В этом случае ядро посылает серверу импульс, а клиент остается заблокированным до тех пор, пока сервер ему не ответит! Это сделано для того, чтобы сервер мог узнать о запросе клиента на разблокирование и выполнить по этому поводу какие-то действия.

2.4.2 Текст программы

 

#include <stdio.h>

#include <pthread.h>

#include <inttypes.h>

#include <errno.h>

#include <sys/neutrino.h>

 

#define SEC_NSEC 1000000000LL // 1 sekynda billion nanosekynd

 

void * long_thread(void *notused)

{

printf("Etot potok vipolnaetsa bolee 10 sekynd \n");

 sleep(20);

}

 

int main(void)

{

uint64_t timeout;

struct sigevent event;

int rval;

pthread_t thread_id;

 

printf("Prog timer \n");

event.sigev_notify = SIGEV_UNBLOCK;

//SIGEV_UNBLOCK_INIT(&event);

pthread_create(&thread_id, NULL, long_thread, NULL);

 

timeout = 10LL*SEC_NSEC;

TimerTimeout(CLOCK_REALTIME, _NTO_TIMEOUT_JOIN,&event, &timeout, NULL);

rval = pthread_join(thread_id, NULL);

if (rval == ETIMEDOUT)

{

printf ("istekli 10 sekynd, potok %d vipolniaetsia!\n", thread_id);

}

sleep(5);

 

TimerTimeout (CLOCK_REALTIME, _NTO_TIMEOUT_JOIN, &event, & timeout, NULL);

rval = pthread_join(thread_id, NULL);

if(rval == ETIMEDOUT)

{

printf("potok %d >25 sek!", thread_id);

}

else

{

printf ("Potok %d zavershon kak nado \n", thread_id);

}

 

return(1);

}

2.4.3 Последовательность действий

Запустить программу на исполнение и сопоставлять то, что она выводит на экран с текстом программы. 

2.4.4 Результаты

 

# cd..

# cd lab2

# ls

.      ..      timer.c timer.exe

# `pwd`/timer.exe

Prog timer

Etot potok vipolnaetsa bolee 10 sekynd

istekli 10 sekynd, potok 2 vipolniaetsia!

Potok 2 zavershon kak nado

#

Лабораторная работа №5 «Синхронизация процессов. Барьры»

2.5.1 Теория

 

Применение барьера

 

Два метода синхронизации: один метод с применением функции pthrea. dJoin(), который мы только что рассмотрели, и метод с применением барьера.

Основной поток должен дождаться того момента, когда все рабочие потоки завершат работу, и только затем можно начинать следующую часть программы.

Однако, с применением функции pthreadJoin () мы ожидаен завершения потоков. Это означает, что на момент ее разблокирования потоков нет больше с нами; они закончили работу и завершились.

В случае с барьером, мы ждем «встречи» определенного числа потоков у барьера. Когда заданное число потоков достигнуто, мы их все разблокируем (заметьте, что потоки при

этом продолжат выполнять свою работу),

Сначала барьер следует создать при помощи функции barrier_ init0:

 

 

#include <sync.h>

int

barrier_init (barrier t        *barrier,

const barrier attr t *attr,

int count);

 

Эта функция создает объект типа «барьер» по переданному ей адресу (указатель на барьер хранится в параметре barrier) и назначает ему атрибуты, которые определены в attr (мы будем использовать NULL, чтобы установить значения по умолчанию). Число потоков, которые должны вызывать функцию barrier_ wait(), передается в параметре count.

После того как барьер создан, каждый из потоков должен будет вызвать функцию barrier_ wait(), чтобы сообщить, что он отработал:

 

#include <sync.h>

int barrier_wait (barrier t *barrier);

После того как поток вызвал barrier_ wait(), он будет блокирован до тех пор, пока число потоков, указанное первоначально в параметре count функции barrier_ mit(), не вызовет функцию barrier'_ waU() (они также будут блокированы). После того как нужное число потоков выполнит вызов функции barrier_ wait(), все эти потоки будут разблокированы «одновременно».

 

 

Текст программы

#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);

}

2.5.3 Последовательность действий

Основной поток создал объект типа «барьер» и инициализировал его значением счетчика, равным числу потоков (включая себя!), которые должны «встретиться» у барьера, прежде чем он «прорвется». В нашем примере этот индекс был равен 3 — один для потока main(), один для потока thread1 () и один для потока thread2(). Затем, как и прежде, стартуют потоки вычисления графики (в нашем случае это потоки thread 1() и thread2()). Для примера вместо приведения реальных алгоритмов графических вычислений мы просто временно «усыпили» потоки, указав в них sleep (20) и sleep (40), чтобы имитировать вычисления. Для осуществления синхронизации основной поток (та in()) просто блокирует сам себя на барьере, зная, что барьер будет разблокирован только после того, как рабочие потоки аналогично присоединятся к нему.

Как упоминалось ранее, с функцией pthreadJoin() рабочие потоки для синхронизации главного потока с ними должны умереть. В случае же с барьером потоки живут и чувствуют себя вполне хорошо. Фактически, отработав, они просто разблокируются по функции barrier•_ wait(). Тонкость здесь в том, что вы обязаны предусмотреть, что эти потоки должны делать дальше! В нашем примере с графикой мы не дали им никакого задания для них — просто потому что мы так придумали алгоритм. В реальной жизни вы могли бы захотеть, например, продолжить вычисления.

 

2.5.4 Результаты

# 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

 

#/**

 


Поделиться с друзьями:

Типы оградительных сооружений в морском порту: По расположению оградительных сооружений в плане различают волноломы, обе оконечности...

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.032 с.