Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
8
Добавлен:
25.02.2016
Размер:
53.19 Кб
Скачать

Министерство образования Республики Беларусь

Белорусский Национальный Технический Университет

Факультет информационных технологий и робототехники

Кафедра «Программное обеспечение вычислительной техники

и автоматизированных систем»

Отчёт

по лабораторной работе № 8

по дисциплине «Операционные системы»

тема: «Основы многозадачности в Linux.

Потоки в Linux»

Исполнитель:

студент группы 10702112

Сидоров А.О.

Преподаватель:

Радкевич А.С.

2013-2014 учебный год

ЛАБОРАТОРНАЯ РАБОТА № 8

Основы многозадачности в Linux.

Потоки в Linux

Цель работы

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

Требования

1) Разработать многопоточное приложение под ОС Linux, которое создаёт несколько потоков для выполнения соответствующих действий и предоставляет управление ими (задание придумать самостоятельно).

2) Приложение должно содержать минимум три потока. Предусмотреть вывод информации о потоках.

3) Для компиляции, компоновки и выполнения программы использовать утилиту make.

Индивидуальное задание:

Задание A

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

  • первый поток: перемещает строку в горизонтальном направлении от одного края терминала до другого;

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

  • третий поток: случайным образом меняет регистр содержимого сроки;

  • четвёртый поток: случайным образом меняет цвет строки.

Задание B

Создать многопоточное приложение, которое создаёт массив целых значений и сортирует его разными методами (к примеру, Шелла, Хоара, пузырька, на основе бинарного дерева и др., но не менее 3). Для каждого вида сортировки создать отдельный поток выполнения. Приложение определяет эффективность использования сортировок путём определения времени выполнения потока.

Ход выполнения лабораторной работы:

  1. В текстовом редакторе gedit набрал исходный код решения задания на языке программирования С++ и сохранил исходник. Программа состоит из следующих файлов:

    • test.cc файл, в котором описана главная функция программы main;

  1. Запустил терминал Linux и с помощью команды cd перешёл в папку местонахождения исходных кодов программы.

  2. Для компиляции программы использовал утилиту make и созданный make-файл.

Результаты выполнения лабораторной работы:

Рисунок 1 — Использование утилиты make

Рисунок 2 — Выполнение программы

Что я освоил в процессе выполнения лабораторной работы:

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

pthread_create – создание потока;

pthread_exit – завершение потока;

pthread_join – ожидание выполнения потока;

pthread_cancel – отмена потока;

pthread_t – структурный тип для хранения идентификатора потока;

pthread_self - возвращает в качестве результата идентификатор вызвавшего ее потока;

pthread_equal — сравнение потоков;

Выводы:

  1. Основными функциями для работы с потоками являются: 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

Соседние файлы в папке Сидоров А.О