Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СРВ_метода_финальная.doc
Скачиваний:
12
Добавлен:
10.11.2019
Размер:
322.56 Кб
Скачать

Лабораторная работа №9 Тема: Создание и отмена потоков- нитей (подпроцессов). Потоковые данные. Синхронизация потоков и критические секции.

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

Теоретические сведения.

В операционных системах нити являются параллельными потоками выполнения в составе одного процесса. (Некоторые переводчики переводят термин "thread" - "нить" – как "поток".) В составе процесса может быть запушено несколько нитей, которые выполняются параллельно (или квазипараллельно - в режиме разделения времени процессора). Можно считать (и в некоторых операционных системах это действительно так), что в любом процессе имеется по крайней мере одна нить - главная - та, в которой выполняется функция main. Главная нить может порождать другие нити. В программе процесса нить имеет вид процедуры/функции, которая вызывается специальным системным вызовом и после вызова выполняется параллельно с запустившей ее нитью.

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

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

  • во-первых, создание нитей происходит быстрее, чем создание процесса, таким образом, нити подходят для задач, требующих быстрого распараллеливания с минимальными накладными расходами (например, распараллеливания выполнения запроса к базе данных);

  • во-вторых, поскольку нити совместно используют ресурсы своего процесса, они являются удобным способом программирования тесно связанных параллельных работ, то есть, таких, которые используют большой объем совместных данных и других ресурсов.

Поскольку статическая память программы - общая для всех нитей, при работе с совместно используемыми переменными возможны конфликты доступа. Конфликты могут возникать при одновременном обращении к таким переменным. Проявляются такие конфликты не в отказе в доступе или в фатальных ошибках, а в возможном нарушении целостности совместно используемых данных. Ответственность за сохранение такой целостности лежит на программисте. Программист должен обеспечить, чтобы логически законченные операции над совместно используемыми данными выполнялись как транзакции, то есть, во время их выполнения другие нити, выполняющиеся параллельно, не могли изменять значения этих же данных. Участки кода программы, выполняющие такую работу с совместно используемыми ресурсами, называются критическими секциями. Для обеспечения целостности требуется, чтобы две или более нитей не могли находиться своих критических секциях одновременно. Это - проблема, наиболее часто возникающая при программировании многопоточных приложений, однако, задачи синхронизации и подсчета ресурсов в таких приложениях также возникают. Для решения этой проблемы можно применять обычные семафоры - как и в аналогичных задачах для процессов. Однако целей работы с нитями во многих операционных системах вводятся специальные средства, предназначенные для обеспечения взаимодействий только в пределах одного процесса. Это «считающие» семафоры (счетчики ресурсов), исключающие семафоры и сигнализирующие семафоры. Фактически все эти средства представляют собой обычные семафоры, используемые только в пределах одного процесса, однако, интерфейсы этих средств отличается от интерфейса семафоров процессов и является более специфичными и удобным в применении.

Стандартами POS1X и Single Unix Specification установлен API для нитей. Стандартный API обеспечивается функциями библиотеки pthread

Ниже перечислены функции <pthread.h>, соответствующие стандарту, которые обеспечивают основные связанные с работой нитей операции в ОС Unix. (Перечислены не все возможности библиотеки pthread).

Функция pthread create создает новую нить. Этой функции передается указатель на атрибуты выполнения нити (большинство нитей выполняется со стандартными атрибутами), указатель на потоковую функцию (функцию, выполняемую в нити), параметр потоковой функции, адрес переменной типа pthread_t, в которую pthread_create записывает идентификатор созданной нити. Функция pthread_create запускает потоковую функцию в новой нити, и она выполняется параллельно с другими нитями процесса.

Синтаксис

# include <pthread.h>

int pthread_create(pthread_t *threadid, pthread attr_t. *attr, void *function, void *arg);

Описание

Функция pthread_create создает новую нить и записывает ее идентификатор по адресу, содержащемуся в аргументе threadid.

Аргумент attr указывает на объект атрибутов нити. При использовании стандартных атрибутов его значение может задаваться NULL.

Аргумент function является адресом функции, выполняемой в нити. Прототип этой функции:

void *имя_функции(void *);

Аргумент arg передается функции, выполняемой в нити.

Возвращаемое значение

При успешном завершении pthread__create возвращает 0. В случае ошибки возвращается ненулевой код.

Потоковая функция имеет прототип:

void * имя функции(void *);

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

Нить завершается при завершении выполнения потоковой функции или при выполнении функции pthread exit.

Функция pthread exit завершает выполнение той нити, из которой она была вызвана. Аргумент value является указателем на данные, возвращаемые нитью, этот указатель может быть получен родительской нитью при помощи функции pthread_ j oin. Действие функции pthread_exit эквивалентно оператору: return value;

Функция pthread_join применяется для нитей так же, как системный вызов wait применяется для процессов: она заставляет вызвавшую ее нить ожидать завершения указанной в вызове нить и позволяет вызвавшей нити получить значение, которое вернула завершившаяся нить.

phtread_join

ожидание завершения нити

Синтаксис

# include <pthread.h>

int pthread_join(pthread_t threadid, void *value);

Описание

Функция pthread_join переводит нить, из которой она была вызвана в состояние ожидания до тех пор, пока не завершится нить, определяемая идентификатором threadid. Аргумент value является указателем на данные, возвращаемые нитью. Если этот аргумент не равен NULL, значение, возвращаемое нитью thread, записывается по адресу value. Это то значение, которое было аргументом функции pthread_exit в нити thread.

Возвращаемое значение

При успешном завершении pthread_join возвращает 0. В случае ошибки возвращается ненулевое значение.

Выполнение нити может быть принудительно прекращено из другой нити при помощи функции pthread_cancel, которой задается идентификатор "убиваемой" нити.

Фактически исключающий семафор является обычным двоичным семафором с начальным значением 1.

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

сс -о name_program name program.о -lpthread

Постановка задачи.

Для заданной в Вашем варианте индивидуального задания предметной области разработайте программную модель ситуации, включающей в себя следующее:

  1. создание главного процесса источника;

  2. порождение нитей для выполнения определённой функции;

  3. присоединение нитей к главной программе.

Отчет по лабораторной работе.

Отчет по лабораторной работе должен содержать:

  • текст программ модели;

  • текстовое или графическое описание алгоритмов функционирования компонентов модели;

  • протокол с результатами работы модели.

Процессы

exec, exit, fork, getpriority, getpid, getppid, nice, setpriority,

wait, waitpid.

Сигналы и временные задержки

alarm, getitimer, kill, nanosleep, raise, setitimer, signal, sleep, usleep.

Средства взаимодействия процессов

msqctl, msgget, msgrcv, msgsnd, semctl, semget, semop, shmat, shmdt, shmctl, shmget.

Нити и их взаимодействие

pthread_cancel, pthread_create, pthread_exit, pthread_join, pthread_mutex_init, pthread_mutex_lock, pthreadjautex_trylock, pthread_mutex_unlock, pthread_cond_broadcast, pthread_cond_init, pthread_cond_signal, pthread_cond_wait, sem_getvalue, sem_init, sem_post, sera_wait

Файлы и каналы

chmod, close, creat, fchmod, lseek, mknod, read, open, pipe, umask, unlink, write

Время и дата

date, gettimeofday, asctime, сtime, gmtime, localtime, mttime,

strftime, time

Обработка ошибок

errno, perror, strerror.

Разное

longjmp, rand, setjmp, srand.

Процессы

execl

execv

execle

execve

execlp

execvp - выполнение файла

exit - нормальное завершение процесса

fork - порождение нового процесса

getpid

getppid - получение идентификатора процесса

nice - изменение приоритета процесса

getpriority

setpriority - чтение/установка приоритета процесса

wait

waitpid - ожидание завершения процесса

Сигналы и временные задержки

alarm - посылка сигнала - будильника

kill - посылка сигнала процессу

nanosleep - точная приостановка процесса

raise - посылка сигнала текущему процессу

getitimer

setitimer - интервальный таймер

signal - обработка сигнала

sleep - приостанов процесса

usleep - приостанов процесса на микросекунды

Средства взаимодействия процессов

msgctl - управление очередью сообщений

msgget - получение идентификатора очереди сообщений

msgrcv - прием сообщений

msgsnd - отправка сообщений

semctl - управляющие операции для семафоров процессов

semget - получение идентификатора для семафоров процессов

semop - семафорные операции для семафоров процессов

shmat

shmdt - присоединение/отсоединение разделяемого сегмента

shmctl - получение идентификатора разделяемого сегмента

shmget - управляющие операции для разделяемого сегмента

Нити и их взаимодействие

pthread_cancel - прекращение нити

pthread_create - запуск нити

pthread_exit - завершение нити

pthread_join - ожидание завершения нити

pthread_mutex_init - инициализация исключающего семафора

pthread_mutex_trylock

pthread_mutex_lock - Р-операция на исключающем семафоре

pthread_mutex_unlock - V-операция на исключающем семафоре

pthread_cond_broadcast - разблокирование нитей, ожидающих на сигнализирующем семафоре

pthread_cond_init - инициализация сигнализирующего семафора

pthread_cond_signal - V-операция на сигнализирующем семафоре

pthread_cond_wait - Р-операция на сигнализирующем семафоре

sem_getvalue - получение значения семафора-счетчика

sem_init - инициализация семафора-счетчика

sem_post - V-операция на семафоре-счетчике

sem_wait - Р-операция на семафоре-счетчике

Файлы и каналы

chmod

fchmod - изменение прав доступа к файлу

close - закрытие файла

creat - создание файла

lsееk - позиционирование в файле

mknod - создание специального файла

open - открытие файла

read - чтение из файла

pipe - создание неименованного канала

umask - изменение режима создания файлов

unlink - уничтожение файла

write - запись в файл

Время и дата

gettimeofday - получение текущего времени

asctime

ctime

gmtime

localtime

mktime - преобразование даты в строку символов

strtime - форматное преобразование даты

time - получение системного времени

Обработка ошибок

errno - номер последней ошибки

perror - системные сообщения об ошибках

strerror - системные сообщения об ошибках

Разное

longjmp

setjmp - нелокальная передача управления

srand

rand - генератор случайных чисел