Разделы презентаций


Fork_Thread

Содержание

Пример 2signal(SIGCHLD,reaper);while(1) { ssock = accept(msock,(struct sockaddr *)&fsin,&len); if(ssock = 0);}Применение процессов для обеспечения параллельной работы сервера

Слайды и текст этой презентации

Слайд 1Применение процессов для обеспечения параллельной работы сервера
Пример 1
#include


int child, i, fd;
char c;
main()
{………………….
for(;;) {

sockclient=accept(………..);
if(child=fork())<0) {
Perror(“Ошибка создания дочернего процесса”);
Exit(1);
}
else if(child==0) {
close(sockMain); /*работа с сокетом клиента*/ Childwork(sockClient); close(sockClient); exit(0);
}
close(sockClient);
}
}
Применение процессов для обеспечения параллельной работы сервераПример 1#include   int child, i, fd; char c;

Слайд 2Пример 2
signal(SIGCHLD,reaper);
while(1) {
ssock = accept(msock,(struct sockaddr

*)&fsin,&len);
if(ssock

об ошибке */ }
switch(fork()) {
case(0):
close(msock);
/* Обработка поступившго запроса ведомым процессом */
close(ssock);
exit(0);
default:
close(ssock);
/* Ведущий процесс */
break;
case -1:
/* Сообщение об ошибке */
}
}
void reaper(int sig)
{int status;
while(wait3(&status,WNOHANG,(struct rusage *)0)>= 0);
}

Применение процессов для обеспечения параллельной работы сервера

Пример 2signal(SIGCHLD,reaper);while(1) {    ssock = accept(msock,(struct sockaddr *)&fsin,&len);      if(ssock

Слайд 3Применение процессов для обеспечения параллельной работы сервера
Замечание: первоначальный, и новые

процессы имеют доступ к открытым сокетам после вызова функции fork()

и они оба должны закрыть эти сокеты, после чего система освобождает связанный с ним ресуры.
Завершившийся процесс остается в виде так называемого процесса-зомби до тех пор, пока родительским процессом не будет выполней системный вызов wait3. Для полного завершения дочернего процесса (т.е. уничтожения процесса-зомби) необходимо перехватывается сигнал завершения дочернего процесса. Операционной системе дается указание, что для ведущего процесса сервера при получении каждого сигнала о завершении работы дочернего процесса (сигнал SIGCHLD) должна быть выполнена функция reaper, в ви­де следующего вызова: signal(SIGCHLD, reaper);
Функция reaper вызывает системную функцию wait3, которая остается забло­кированной до тех пор, пока не произойдет завершение работы одного или нескольких дочерних процессов. Эта функция возвращает значение структуры status, которую можно проанализировать для получения до­полнительной информации о завершившемся процессе. Поскольку данная программа вызывает функцию wait3 при получении сигнала SIGCHLD, вызов этой функции всегда происходит только после завершения работы дочернего процес­са. Для предотвращения возникновения в сервере тупиковой ситуации в случае ошибочного вызова в программе используется параметр WNOHANG, который указывает, что функция wait3 не должна блокироваться в ожидании завершения како­го-либо процесса.
Применение процессов для обеспечения параллельной работы сервераЗамечание: первоначальный, и новые процессы имеют доступ к открытым сокетам после

Слайд 4int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

После

создания нового потока в нем начинается выполняться функция (которая называется

потоковой функцией), переданная параметром start_routine, причем ей самой в качестве первого параметра передается переменная arg. Параметр attr позволяет задать атрибуты потока (NULL для значений по умолчанию). thread -- адрес переменной, в которую pthread_create() записывает идентификатор созданного потока. Созданный с помощью pthread_create() поток будет работать параллельно с существующими. Возвращается 0 в случае успеха и не ноль -- в противоположном случае. Потоковая функция start_routine имеет прототип:

void* my_thread_function(void *);

Поскольку как параметр, так и ее возвращаемое значение -- указатели, то функция может принимать в качестве параметра и возвращать любую информацию.

Применение потоков для обеспечения параллельной работы сервера

int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);	После создания нового потока в нем начинается выполняться

Слайд 5Выполнение потока завершается в двух случаях: если завершено выполнение потоковой

функции, или при выполнении функции pthread_exit():

void pthread_exit(void *retval);

которая завершает выполнение вызвавшего ее потока. Аргумент retval -- это код с которым завершается выполнение потока. При завершении работы потока вы должны помнить, что pthread_exit() не закрывает файлы и все открытые потоком файлы будут оставаться открытыми даже после его завершения, так что не забывайте подчищать за собой. Если вы завершите выполнение функции main() с помощью pthread_exit(), выполнение порожденных ранее потоков продолжится.

Применение потоков для обеспечения параллельной работы сервера

Выполнение потока завершается в двух случаях: если завершено выполнение потоковой функции, или при выполнении функции pthread_exit(): void

Слайд 6Потоки, как и порожденные процессы, по завершению работы сами по

себе не освобождают ресурсы, занятые собой для личного пользования (а

именно дескриптор и стек) :-) . Поэтому им необходимо помочь.
Варианта, собственно, два: либо на ряду с освобождением ресурсов какой-либо поток ждет его завершения, либо нет.
Для первого варианта используем функцию pthread_join():

int pthread_join(pthread_t th, void **thread_return);

которая приостанавливает выполнение вызвавшего ее процесса до тех пор, пока поток, определенный параметром th, не завершит свое выполнение и если параметр thread_return не будет равен NULL, то запишет туда возвращенное потоком значение (которое будет равным либо PTHREAD_CANCELED, если поток был отменен, либо тем значением, которое было передано через аргумент функции pthread_exit()).

Применение потоков для обеспечения параллельной работы сервера

Потоки, как и порожденные процессы, по завершению работы сами по себе не освобождают ресурсы, занятые собой для

Слайд 7Для второго варианта есть функция pthread_detach() :

int pthread_detach(pthread_t th);

которая

делает поток th "открепленным" (detached). Это значит, что после того,

как он завершится, он сам освободит все занятые ним ресурсы.

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

Применение потоков для обеспечения параллельной работы сервера

Для второго варианта есть функция pthread_detach() : int pthread_detach(pthread_t th);	которая делает поток th

Слайд 8Cоздание потоков позволяет им совместно использовать некоторые ресурсы, но нужно

производить контроль на предмет эксклюзивности доступа к этим ресурсам (нельзя

допускать одновременной записи в одну переменную, например).

Такой контроль можно вести тремя способами через:

взаимоисключающую блокировку
условные переменные
Семафоры

Применение потоков для обеспечения параллельной работы сервера

Cоздание потоков позволяет им совместно использовать некоторые ресурсы, но нужно производить контроль на предмет эксклюзивности доступа к

Слайд 9Первый вариант представляется самим набором функций библиотеки POSIX Threads. Взаимоисключающая

блокировка представляется в программе переменной типа pthread_mutex_t.
Для работы с

ними существует 5 функций, а именно:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
которая инициализирует блокировку, заданную параметром mutex. Соответственно, mutexattr -- ее атрибуты. Значение NULL соответствует установкам по умолчанию.

int pthread_mutex_destroy(pthread_mutex_t *mutex);
удаляет блокировку mutex

Применение потоков для обеспечения параллельной работы сервера

Первый вариант представляется самим набором функций библиотеки POSIX Threads. Взаимоисключающая блокировка представляется в программе переменной типа pthread_mutex_t.

Слайд 10int pthread_mutex_lock(pthread_mutex_t *mutex)

устанавливает блокировку mutex. Если mutex

не была заблокирована, то она его ее и немедленно завершается.

Если же нет, то функция приостанавливает работы вызвавшего ее потока до разблокировки mutex, а после этого выполняет аналогичные действия.

int pthread_mutex_unlock(pthread_mutex_t *mutex)

снимает блокировку mutex. Подразумевается, что эта функция будет вызвана тем же потоком, который ее заблокировал (через pthread_mutex_lock()).

int pthread_mutex_trylock(pthread_mutex_t *mutex)

ведет себя аналогично pthread_mutex_lock() за исключением того, что она не приостанавливает вызывающий поток, если блокировка mutex установлена, а просто завершается с кодом EBUSY.

Применение потоков для обеспечения параллельной работы сервера

int pthread_mutex_lock(pthread_mutex_t *mutex)   устанавливает блокировку mutex. Если mutex не была заблокирована, то она его ее

Слайд 11Поток выполнения представляет собой один из принципов организации отдельных вычислений,

а один процесс может содержать от одного и более потоков.


Новый поток может быть создан в любое время путем вызова функции pthread_create.
Операционная система ограничивает максимально допустимое количество параллельных потоков, также как и максимальное количество параллельных процессов.
Все потоки процесса разделяют единый набор глобальных переменных и единый набор дескрипторов файлов.
Многопотоковые процессы обладают двумя основными преимуществами по сравнению с однопотоковыми процессами:

более высокая эффективность и разделяемая память.

Повышение эффективности связано с уменьшением издержек на переключение контекста.

Применение потоков для обеспечения параллельной работы сервера

Поток выполнения представляет собой один из принципов организации отдельных вычислений, а один процесс может содержать от одного

Слайд 12Переключение контекста –

это действия, выполняемые операционной

системой при передаче ресурсов процессора от одного потока выполнения к

другому.
При переключении с одного потока на другой операционная система должна сохранить в памяти состояние предыдущего потока (например, значения регистров) и восстановить состояние следующего потока.
Потоки в одном и том же процессе разделяют значительную часть информации о состоянии процесса, поэтому операционной системе приходится выполнять меньший объем работы по сохранению и восстановлению состояния.
Вследствие этого переключение с одного потока на другой в одном и том же процессе происходит быстрее по сравнению с переключением между двумя потоками в разных процессах.

Применение потоков для обеспечения параллельной работы сервера

Переключение контекста –   это действия, выполняемые операционной системой при передаче ресурсов процессора от одного потока

Слайд 13Второе преимущество потоков (разделяемая память), является более важным, чем повышение

эффективности.

Потоки упрощают разработку параллельных серверов, в которых все копии

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

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

Применение потоков для обеспечения параллельной работы сервера

Второе преимущество потоков (разделяемая память), является более важным, чем повышение эффективности. 				Потоки упрощают разработку параллельных серверов, в

Слайд 14Еще один недостаток связан с отсутствием надежности.

Если одна из

параллельно работающих копий однопотокового сервера вызовет серьезную ошибку (например, в

ней будет выполнена ссылка на недопустимую область памяти), то операционная система завершит только тот процесс, который вызвал ошибку. С другой стороны, если серьезная ошибка будет вызвана одним из потоков многопотокового сервера, то операционная система завершит весь процесс (т.е. все потоки этого процесса).

Применение потоков для обеспечения параллельной работы сервера

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

Слайд 15struct {pthread_mutex_t st_mutex; /* Разделяемая переменная */
} GLOBAL;

int main()

{
pthread_t th;
pthread_attr_t ta;
/* Создаем ведущий сокет, привязываем его

к общепринятому порту и переводим в пассивный режим */
pthread_attr_init(&ta);
pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
pthread_mutex_init(&GLOBAL.st_mutex,0);
while (1) {ssock = accept(msock, (struct sockaddr *)&fsin, &len);
if (ssock <0) {/* ошибка */}
if (pthread_create(&th, &ta, (void * (*)(void *))handler, (void *)ssock) <0) {/* ошибка */}
}

int handler(int ssock)
{pthread_mutex_lock(&GLOBAL.st_mutex);
/* выполнение операций с разделяемыми переменными */
pthread_mutex_unlock(&GLOBAL.st mutex);
return 0;
}

Пример сервера, реализованного с применением потоков

struct {pthread_mutex_t st_mutex;  /* Разделяемая переменная */} GLOBAL;int main() {pthread_t  th;pthread_attr_t  ta;/* Создаем ведущий

Слайд 16Аргумент attr содержит атрибуты, присваиваемые вновь создаваемому потоку. Значение аргумента

может быть равно NULL, если новый поток должен использовать атрибуты,

принятые системой по умолчанию, или адрес объекта содержит атрибуты. Объект, содержащий атрибуты, может быть связан с несколькими потоками.
Функция pthread_attr_init создает объект, содержащий атрибуты, а функция phread_attr_destroy удаляет такой объект:
#include
Int pthread_attr_init(pthread_attr_t* attr_p);
Int pthread_attr_destroy(pthread_attr_t* attr_p);

Атрибуты объекта, созданного функцией pthread_attr_init, можно проверить функцией pthread_attr_get, или установить функцией pthread_attr_set .
Например, состояние отсоединения
API для проверки - pthread_attr_getdetachstate
API для установки - pthread_attr_setdetachstate

Применение потоков для обеспечения параллельной работы сервера

Аргумент attr содержит атрибуты, присваиваемые вновь создаваемому потоку. Значение аргумента может быть равно NULL, если новый поток

Слайд 17#include
#include
#include
#include
#include
#include

#define NTHRDS 2 /*

К этим ресурсам мы можем получить доступ из потока

*/

char words[8000][20]; // Словарь
int current, maxw;
char foundpass; // Флажок

pthread_mutex_t mutexpass, mutexfound; /* Блокировки */

void *passhack(void *hash)

int main(int argc, char **argv)
{
char i, *pass;
FILE *passfile;

Применение потоков для обеспечения параллельной работы сервера

#include #include #include #include #include #include #define NTHRDS 2 /* К этим ресурсам мы можем получить

Слайд 18pthread_t thrds[NTHRDS]; // Потоки
pass = (char *)malloc(35);
pthread_mutex_init(&mutexpass,

NULL); /* Инициализация блокировок */
pthread_mutex_init(&mutexfound, NULL);
strcpy(pass, argv[1]); /*

Читаем словарь в память */
strcpy(pass, argv[1]); /* Читаем словарь в память */
passfile = fopen(argv[2], "r");
maxw = 0;
while (!feof(passfile)) fgets(words[maxw++], 20, passfile);
fclose(passfile);
foundpass = 0;
/* Запускаем потоки */
for (i=0;i < NTHRDS;i++)
pthread_create(&thrds[i], NULL, passhack, (void *) pass);
/* И ждем завершения их работы */
for (i=0;i < NTHRDS;i++)
pthread_join(thrds[i], NULL);

/* Освобождаем блокировки */
pthread_mutex_destroy(&mutexpass);
pthread_mutex_destroy(&mutexfound);
return 0;
}

Применение потоков для обеспечения параллельной работы сервера

pthread_t thrds[NTHRDS];  // Потоки pass = (char *)malloc(35); pthread_mutex_init(&mutexpass, NULL); /* Инициализация блокировок */ pthread_mutex_init(&mutexfound, NULL);

Слайд 19Аргумент attr содержит атрибуты, присваиваемые вновь создаваемому потоку. Значение аргумента

может быть равно NULL, если новый поток должен использовать атрибуты,

принятые системой по умолчанию, или адрес объекта содержит атрибуты. Объект, содержащий атрибуты, может быть связан с несколькими потоками.
Функция pthread_attr_init создает объект, содержащий атрибуты, а функция phread_attr_destroy удаляет такой объект:

#include
Int pthread_attr_init(pthread_attr_t* attr_p);
Int pthread_attr_destroy(pthread_attr_t* attr_p);


Применение потоков для обеспечения параллельной работы сервера

Аргумент attr содержит атрибуты, присваиваемые вновь создаваемому потоку. Значение аргумента может быть равно NULL, если новый поток

Слайд 20Атрибуты объекта, созданного функцией pthread_attr_init, можно проверить функцией pthread_attr_get, или

установить функцией pthread_attr_set .
Например,
состояние отсоединения
API

для проверки - pthread_attr_getdetachstate
API для установки - pthread_attr_setdetachstate
правила планирования
API для проверки - pthread_attr_getschedpolicy
API для установки – pthread_attr_setschedpolicy
Правила планирования задают, среди прочего, приоритет потока
Параметры планирования
API для проверки - pthread_attr_getschedparam
API для установки - pthread_attr_setschedparam
Второй аргумент в pthread_attr_getschedparam и pthread_attr_setschedparam – это адрес переменной типа struct sched_param . В этой переменной есть целочисленное поле sched_priority, в котором задается приоритет любогопотока, обладающего этим свойством.

Применение потоков для обеспечения параллельной работы сервера

Атрибуты объекта, созданного функцией pthread_attr_init, можно проверить функцией pthread_attr_get, или установить функцией pthread_attr_set .Например, состояние отсоединения

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика