УТС 4 семестр / Lab1_Oreshchenko
.docxМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра ИС
отчет
по лабораторной работе № 1 по дисциплине
«Операционные системы»
Тема: Создание и уничтожение потоков
Студент гр. 8391 |
|
Орещенко Н.В. |
Преподаватель |
|
Широков В.В. |
Санкт-Петербург
2020
Цель работы - знакомство с базовой структурой построения
многопоточной программы и с системными вызовами, обеспечивающими
создание и завершение потоков.
Общие сведения
Базовая структура многопоточной программы, взятая за основу всех
работ, выглядит следующим образом:
Описываются поточные функции, соответствующие потокам программы.
В основной программе создаются потоки на основе поточных функций.
После создания потоков основная программа приостанавливает выполнение и ожидает команды завершения.
При поступлении команды завершения основная программа формирует команды завершения потоков.
Основная программа переходит к ожиданию завершения потоков.
После завершения потоков основная программа завершает свою работу.
Создание потока в стандарте POSIX осуществляется следующим
вызовом:
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg),
где:
thread – указатель на идентификатор потока;
attr – указатель на структуру данных, описывающих атрибуты потока;
start_routine – имя функции, выполняющей роль потока;
arg - указатель на структуру данных, описывающих передаваемые в поток
параметры.
Завершение работы потока может быть выполнено несколькими
способами.
1. Вызовом оператора return из функции потока;
2. Вызовом функции:
int pthread_cancel(pthread_t thread);
из другого потока;
3. Вызовом функции:
int pthread_exit(void *value_ptr).
В последнем случае появляется возможность через переменную
value_ptr передать в основной поток “код завершения”.
При этом необходимо синхронизировать завершение с основным
потоком, используя следующую функцию:
int pthread_join(pthread_t thread, void **retval),
где:
thread – идентификатор потока;
retval – код завершения потока, переданный через функцию pthread_exit.
Функция, выполняющая роль потока, создается на основе следующего
шаблона:
static void * thread_start(void *arg).
Реализация
#include <iostream>
#include <pthread.h>
#include <unistd.h>
void *thread1(void* arg){
bool* flag1 = (bool*) arg;
while(!*flag1){
std::cout << "1\n";
sleep(1);
}
int *code = new int;
*code = 11;
pthread_exit(code);
}// thread1
void *thread2(void* arg){
bool* flag2 = (bool*) arg;
while(!*flag2){
std::cout << "2\n";
sleep(1);
}
int *code = new int;
*code = 22;
pthread_exit(code);
}// thread2
int main()
{
pthread_t id1, id2;
bool flag1 = false, flag2 = false;
int *code1, *code2;
pthread_create(&id1, NULL, &thread1, &flag1);
pthread_create(&id2, NULL, &thread2, &flag2);
getchar();
flag1 = flag2 = true;
pthread_join(id1, (void **)&code1);
pthread_join(id2, (void **)&code2);
std::cout << "\nПоток 1 завершился с кодом: " << *code1;
std::cout << "\nПоток 2 завершился с кодом: " << *code2 << "\n";
delete code1;
delete code2;
return 0;
}//main
Демонстрация
Рис. 1 Работа потоков
Рис. 2 Завершение работы потоков, вывод кода.
Ответы на вопросы
В чем состоит различие между понятиями «поток» и «процесс»? Процесс - независимый объект, которому выделены системные ресурсы. В ОС каждому процессу соответствует адресное пространство и управляющий поток. Поток — определенный способ выполнения процесса.
Как осуществить передачу параметров в функцию потока при создании потока? Рассмотрим создание потока: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg), где arg - указатель на структуру данных, описывающих передаваемые в поток параметры.
Какие способы завершения потока существуют?
Вызовом оператора return из функции потока;
int pthread_cancel(pthread_t thread); из другого потока;
int pthread_exit(void *value_ptr).
На какие характеристики потока можно влиять через атрибуты потока?
Атрибут |
Значение default |
Смысл |
scope |
PTHREAD_SCOPE_PROCESS |
Новый поток не ограничен - не присоединен ни к одному процессу |
detachstate |
PTHREAD_CREATE_JOINABLE |
Статус выхода и поток сохраняются после завершения потока |
stackaddr |
NULL |
Новый поток получает адрес стека, выделенного системой |
stacksize |
1 Мбайт |
Новый поток имеет размер стека, определенный системой |
schedpolicy |
SCHED_OTHER |
Новый поток использует диспетчеризацию с фиксированными приоритетами. Поток работает, пока не будет прерван потоком с высшим приоритетом или не приостановится |
В каких состояниях может находиться поток?
Выполнение
Ожидание
Готовность
Какие способы переключения задач используются в ОС?
Круговой. Управление между задачами производится в каком-либо фиксированном порядке через определённые промежутки времени;
Случайный. Через каждый определённый промежуток времени управление передаётся на произвольную задачу;
Приоритетный. Каждая задача имеет уровень приоритета и управление получает незаблокированная задача имеющая наибольший уровень;
Управляемая дедлайнами. Передача управления производится в порядке, обеспечивающем выполнение задач в определённый срок.
Объясните суть параметров, входящих в вызов pthread_create(). int pthread_create( pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
thread – указатель на идентификатор потока;
attr – указатель на структуру данных, описывающих атрибуты потока;
start_routine – имя функции, выполняющей роль потока;
arg - указатель на структуру данных, описывающих передаваемые в поток параметры.
Объясните суть параметров, входящих в вызов pthread_join(). int pthread_join( pthread_t thread, void **retval);
thread – идентификатор потока;
retval – код завершения потока, переданный через функцию pthread_exit.
Опишите трассу выполнения программы. объявление функций потоков;
основная программа {
объявление идентификаторов потоков;
объявление флагов;
объявление кодов завершения;
создание потоков из функций потоков;
ожидание нажатия клавиши;
смена флагов;
ожидание завершения потоков;
вывод кодов;
}
Вывод: в результате проделанной лабораторной работы я познакомился с базовой структурой построения многопоточной программы, а также изучил системные вызовы, которые обеспечивают создание и завершение потоков.