Сидоров А.О / ос8
.docx
Министерство образования Республики Беларусь
Белорусский Национальный Технический Университет
Факультет информационных технологий и робототехники
Кафедра «Программное обеспечение вычислительной техники
и автоматизированных систем»
Отчёт
по лабораторной работе № 8
по дисциплине «Операционные системы»
тема: «Основы многозадачности в Linux.
Потоки в Linux»
Исполнитель: |
|
студент группы 10702112 Сидоров А.О. |
Преподаватель: |
|
Радкевич А.С. |
2013-2014 учебный год
ЛАБОРАТОРНАЯ РАБОТА № 8
Основы многозадачности в Linux.
Потоки в Linux
Цель работы
Изучить фундаментальные концепции, связанные с разработкой многопоточных приложений в Linux.
Требования
1) Разработать многопоточное приложение под ОС Linux, которое создаёт несколько потоков для выполнения соответствующих действий и предоставляет управление ими (задание придумать самостоятельно).
2) Приложение должно содержать минимум три потока. Предусмотреть вывод информации о потоках.
3) Для компиляции, компоновки и выполнения программы использовать утилиту make.
Индивидуальное задание:
Задание A
Создать многопоточное приложение, в котором создаются 4 потока, каждый из которых работает параллельно главному потоку и выполняют следующие действия:
-
первый поток: перемещает строку в горизонтальном направлении от одного края терминала до другого;
-
второй поток: случайным образом меняет содержимое строки;
-
третий поток: случайным образом меняет регистр содержимого сроки;
-
четвёртый поток: случайным образом меняет цвет строки.
Задание B
Создать многопоточное приложение, которое создаёт массив целых значений и сортирует его разными методами (к примеру, Шелла, Хоара, пузырька, на основе бинарного дерева и др., но не менее 3). Для каждого вида сортировки создать отдельный поток выполнения. Приложение определяет эффективность использования сортировок путём определения времени выполнения потока.
Ход выполнения лабораторной работы:
-
В текстовом редакторе gedit набрал исходный код решения задания на языке программирования С++ и сохранил исходник. Программа состоит из следующих файлов:
-
test.cc – файл, в котором описана главная функция программы main;
-
Запустил терминал Linux и с помощью команды cd перешёл в папку местонахождения исходных кодов программы.
-
Для компиляции программы использовал утилиту make и созданный make-файл.
Результаты выполнения лабораторной работы:
Рисунок 1 — Использование утилиты make
Рисунок 2 — Выполнение программы
Что я освоил в процессе выполнения лабораторной работы:
-
Изучил основные функции для работы с потоками:
pthread_create – создание потока;
pthread_exit – завершение потока;
pthread_join – ожидание выполнения потока;
pthread_cancel – отмена потока;
pthread_t – структурный тип для хранения идентификатора потока;
pthread_self - возвращает в качестве результата идентификатор вызвавшего ее потока;
pthread_equal — сравнение потоков;
Выводы:
-
Основными функциями для работы с потоками являются: pthread_create, pthread_exit, pthread_join, pthread_cancel, pthread_self ,pthread_equal .
ПРИЛОЖЕНИЕ A
Листинг исходного кода программы
Файл test.cc
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
using namespace std;
static const char * cp_black = "\x1b[30;1m";
static const char * cp_red = "\x1b[31;1m";
static const char * cp_green = "\x1b[32;1m";
static const char * cp_yellow = "\x1b[33;1m";
static const char * cp_orange = "\x1b[33;1m";
static const char * cp_blue = "\x1b[34;1m";
static const char * cp_purple = "\x1b[35;1m";
static const char * cp_lightblue = "\x1b[36;1m";
static const char * cp_white = "\x1b[37;1m";
static const char * cp_stop = "\x1b[0m";
pthread_mutex_t m;
struct thread_arg
{
char *str;
int n;
};
void *thread_func1 (void * arg)
{
struct thread_arg targ = *(struct thread_arg*) arg;
char *pro=new char[targ.n+1];
for (int i=0;i<targ.n+1;i++){
system("clear");
pthread_mutex_lock(&m);
cout<<pro<<targ.str<<endl<<cp_stop;
pthread_mutex_unlock(&m);
sleep(1);
pro[i]=' ';}
cout<<cp_white<<endl<<cp_stop;
return NULL;
}
void *thread_func2 (void * arg)
{
struct thread_arg targ = *(struct thread_arg*) arg;
int l,k1,k2;
l = strlen(targ.str);
while(1){
sleep(1);
k1=0+rand()%l;
pthread_mutex_lock(&m);
for(int i=0;i<k1;i++)
{
k2=0+rand()%l;
if (isupper(targ.str[k2])) {targ.str[k2]=tolower(targ.str[k2]);}
else {targ.str[k2]=toupper(targ.str[k2]);}
}
pthread_mutex_unlock(&m);
}
return NULL;
}
void *thread_func3 (void * arg)
{
struct thread_arg targ = *(struct thread_arg*) arg;
int l,k1,k2;
l = strlen(targ.str);
while(1){
sleep(1);
k1=0+rand()%l;
pthread_mutex_lock(&m);
for(int i=0;i<k1;i++)
{
k2=0+rand()%l;
int i1=0+rand()%2;
if (targ.str[k2]!=' '){
if (i1==0){targ.str[k2]=rand()%26 + 'A';}
else {targ.str[k2]=rand()%26 + 'a';} }
}
pthread_mutex_unlock(&m);
}
return NULL;
}
void *thread_func4 (void * arg)
{
struct thread_arg targ = *(struct thread_arg*) arg;
int k1;
while(1){
sleep(1);
k1=0+rand()%9;
pthread_mutex_lock(&m);
if (k1==0){cout<<cp_black;}
else if(k1==1){cout<<cp_red;}
else if(k1==2){cout<<cp_green;}
else if(k1==3){cout<<cp_yellow;}
else if(k1==4){cout<<cp_orange;}
else if(k1==5){cout<<cp_blue;}
else if(k1==6){cout<<cp_purple;}
else if(k1==7){cout<<cp_lightblue;}
else {cout<<cp_white;}
pthread_mutex_unlock(&m);
}
return NULL;
}
int main (int size,char **argv)
{
int result;
pthread_mutex_init(&m,NULL);
pthread_t thread1, thread2 ,thread3,thread4;
struct thread_arg targ;
struct winsize w;
ioctl(1,TIOCGWINSZ,&w);
targ.str=new char[128];
cout<<"Введите строку: ";
cin.getline(targ.str,128);
targ.n=w.ws_col-strlen(targ.str);
result = pthread_create (&thread1, NULL, &thread_func1, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_create (&thread2, NULL, &thread_func2, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_create (&thread3, NULL, &thread_func3, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_create (&thread4, NULL, &thread_func4, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_join(thread1, NULL);
if (result != 0) {
perror("Ждём первый поток");
return EXIT_FAILURE;
}
return 0;
}
Файл Makefile
test: test.o
g++ test.o -o test -lpthread
test.o: test.cc
g++ -c test.cc
ПРИЛОЖЕНИЕ B
Листинг исходного кода программы
Файл test.cc
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
using namespace std;
struct timespec tw2 = {0,000100000};
struct timespec tw3 = {0,000600000};
struct timespec tr;
struct timeval tsa, tse, tpa, tpe, tva, tve;
struct thread_arg
{
int *massiv;
int n;
};
void *thread_func1 (void * arg)
{
cout<<"Идентификатор 1 потока: "<<pthread_self()<<endl;
struct thread_arg targ = *(struct thread_arg *) arg;
int *a=new int [targ.n];
memcpy(a, targ.massiv, sizeof(int)*targ.n);
int N=targ.n;
gettimeofday(&tsa, NULL);
for(int d=N/2; d > 0; d/=2)
for(int i=d; i < N; i++)
for(int j = i; j>=d && a[j - d] > a[j]; j -= d)
swap(a[j], a[j-d]);
gettimeofday(&tse, NULL);
printf("Время выполнения сортировки Шелла: %lf sec\n", tse.tv_sec - tsa.tv_sec + (tse.tv_usec - tsa.tv_usec)/1000000.0);
return NULL;
}
void *thread_func2 (void * arg)
{
nanosleep (&tw2, &tr);
cout<<"Идентификатор 2 потока: "<<pthread_self()<<endl;
int i,j;
struct thread_arg targ = *(struct thread_arg *) arg;
int *a=new int [targ.n];
memcpy(a, targ.massiv, sizeof(int)*targ.n);
int N=targ.n;
gettimeofday(&tpa, NULL);
for(i = 0 ; i < N ; i++) {
for(j = 0 ; j < N - i - 1 ; j++) {
if(a[j] > a[j+1]) {
swap(a[j], a[j + 1]);
}
}
}
gettimeofday(&tpe, NULL);
printf("Время выполнения сортировки пузырьком: %lf sec\n", tpe.tv_sec - tpa.tv_sec + (tpe.tv_usec - tpa.tv_usec)/1000000.0);
return NULL;
}
void *thread_func3 (void * arg)
{
nanosleep (&tw3, &tr);
cout<<"Идентификатор 3 потока: "<<pthread_self()<<endl;
int i,j;
struct thread_arg targ = *(struct thread_arg *) arg;
int *a=new int [targ.n];
memcpy(a, targ.massiv, sizeof(int)*targ.n);
int N=targ.n;
gettimeofday(&tva, NULL);
for (int i = 0; i < N; i++)
{
int min = i;
for (int j = i + 1; j < N; j++)
{
if (a[j] < a[min])
{
min = j;
}
}
swap (a[i], a[min]);
}
gettimeofday(&tve, NULL);
printf("Время выполнения сортировки выбором: %lf sec\n", tve.tv_sec - tva.tv_sec + (tve.tv_usec -tva.tv_usec)/1000000.0);
return NULL;
}
int main (int size,char **argv)
{
pthread_t thread1, thread2 ,thread3;
int n,m,result;
cout<<"Введите длину массива: ";
cin>>n;
struct thread_arg targ;
targ.massiv=new int[n];
srand(time(NULL));
for (int i=0; i<n; i++)
{
m = 0 + rand() % 100;
targ.massiv[i]=m;
}
targ.n=n;
result = pthread_create (&thread1, NULL, &thread_func1, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_create (&thread2, NULL, &thread_func2, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_create (&thread3, NULL, &thread_func3, &targ);
if (result != 0)
{
perror("Ошибка!");
return EXIT_FAILURE;
}
result = pthread_join(thread1, NULL);
if (result != 0) {
perror("Ждём первый поток");
return EXIT_FAILURE;
}
result = pthread_join(thread2, NULL);
if (result != 0) {
perror("Ждём второй поток");
return EXIT_FAILURE;
}
result = pthread_join(thread3, NULL);
if (result != 0) {
perror("Ждём третий поток");
return EXIT_FAILURE;
}
return 0;
}
Файл Makefile
test: test.o
g++ test.o -o test -lpthread
test.o: test.cc
g++ -c test.cc