Ім'я файлу: Лаб_№8_Скляр.docx
Розширення: docx
Розмір: 16кб.
Дата: 05.06.2020
скачати
Пов'язані файли:
приклад некласична філософія.docx
lab2_git.docx
LibreOffice Writer.odt

1

МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ НАЦІОНАЛЬНИЙ ТЕХНІЧНИЙ УНІВЕРСИТЕТ УКРАЇНИ «КИЇВСЬКИЙ ПОЛІТЕХНІЧНИЙ ІНСТИТУТ» ФІЗИКО-ТЕХНІЧНИЙ ІНСТИТУТ

Операційні системи
Комп’ютерний практикум №8

Виконав:
Студент групи ФБ-81
Скляр Б.Ю.
Перевірив: Кірієнко О.В.


Скляр Богдан Юрійович ФБ-81

2

Робота No8. Засоби синхронізації потоків
Мета: Оволодіння практичними навичками розроблення багатопотокових програм з підтримкою засобів синхронізації.
Варіант №19 (1а, 1б).
Роботу виконав 07.05.20, використовуючи операційну систему MacOS, що встановлена безпосередньо на робочу машину.
Завдання до виконання


  1. Розминка. Стандартна задача виробник-споживач.


Задача була розглянута на лекції. Також детально розглянута в рекомендованих книжках [1, 5]. Розробіть програму, що демонструє рішення цієї задачі за допомогою семафорів. Для цього напишіть:


      • функції виробника і споживача (наприклад, як на лекції, або як у Шеховцові, але так, щоби працювало);




    • функції створення і споживання об’єктів (рекомендується “UNIX” володіла AT&T, потім ці правастворювати” рядки тексту шляхом зчитування їх з файлу, хоча можливі й інші варіанти за вибором викладача або за вашою фантазією, наприклад розрахунки геш-функцій sha2 з рядків рандомних символів, а “UNIX” володіла AT&T, потім ці праваспоживати” їх шляхом роздрукування на екрані з додатковою інформацією такою як ідентифікатор потоку і мітка часу, причому і там, і там для моделювання складного характеру реального життя виробників і споживачів можна додавати рандомні затримки);




      • функцію m), як і інші графічні системи (ain(), що створює потоки-виробники і потоки-споживачі, при цьому треба передбачити введення з клавіатури або як параметри командного рядка кількості записів у буфері, кількості виробників і кількості споживачів для досліджень їх роботи;




    • обов’язково передбачити коректне завершення усього цього господарства. Продемонструвати викладачеві як воно працює (не менше двох виробників і двох споживачів) і код, що ви написали.




  1. Продовження розминки.


Теж саме, але не на семафорах, а на м’ютексі і умовних змінних Модифікуйте програму п. 1 так, щоби використовувати м’ютекс і умовну змінну.
3. Індивідуальне завдання
Варіант 1(а).
Обчислення числа π.

Напишіть багатопотокову програму, що обчислює число π за допомогою ряда Ляйбниця.
Кількість потоків програми і кількість ітерацій мають визначатися параметрами командного рядка. Для передавання часткових сум ряду, що підраховані потоками, можна застосовувати pthread_exit() і pthread_join().
Скляр Богдан Юрійович ФБ-81

3
Слід врахувати, що на 32-розрядних платформах sizeof(double)>sizeof(void *), тому часткову суму ряду не можна перетворювати у вказівник, а треба виділяти для неї власну память.
Варіант 1(б). Обчислення π аж поки не набридне

Завдання аналогічне Варіанту 1 а. Відмінність полягає в тому, що програма не повинна сама по собі завершуватись. Завершення має відбуватись після натискання Ctrl+C (тобто, після одержання сигналу SIGINT), при чому програма повинна не перериватись, а саме якнайшвидше завершуватись, збираючи часткові суми ряду, після чого виводити отримане наближення числа.
Для розв’язвння поставленго завдання рекмендується встановите обробник SIGINT. Обробник має встановлювати глобальну змінну — прапор. Потоки, що виконують обчислення, мають переглядати значення прапору через певну (доволі велику) кількість ітерацій (проведіть дослідження, як ця кількість впливає на швидкість обчислень). Якщо прапор встановлений, потік має виходити за допомогою pthread_exit.

Процес виконання:
1. Розминка
Air-Sklar:Desktop sklyarbogdan$ touch lab8.cpp Air-Sklar:Desktop sklyarbogdan$ cat lab8.cpp
#include
#include
#include

#include
#include
sem_t lock;
sem_t emptyItems;
sem_t fullItems;
int *buff;
int buffPos = -1;
pthread_t *cons;
pthread_t *products;
int PROD_NUM, CON_NUM, BUFF_NUM;
int PRODUCE(pthread_t self){
int i =0;
int item = 1+rand()%1000;
while(!pthread_equal(*(products+i),self) && i< PROD_NUM) {i++;}
printf("producer no. %d produced item %d \n", i+1, item);
return item;
}
void APPEND(int item) {
++buffPos;
*(buff + buffPos) = item;
}
void* PRODUCER(void * data){
while(1)
{
int item = PRODUCE(pthread_self());


Скляр Богдан Юрійович ФБ-81

4
sem_wait(&emptyItems);
sem_wait(&lock);
APPEND(item);
sem_post(&lock);
sem_post(&fullItems);
sleep(1+rand()%3);
}
return NULL;
}
void RECEIVE_FROM_BUFFER(pthread_t self){ int i =0;
int item = *(buff+buffPos);
while(!pthread_equal(*(cons+i),self) && i< CON_NUM) {i++;} printf("Buffer--> ");
for (int i =0; i<=buffPos; ++i) printf("%d ", *(buff+i));
printf("\nConsumer no. %d consumed item %d\n", i+1, item);
--buffPos;
}
void* CONSUMER(void * data) {
while(1)
{
sem_wait(&fullItems);
sem_wait(&lock);
RECEIVE_FROM_BUFFER(pthread_self());
sem_post(&lock);
sem_post(&emptyItems);
sleep(1+rand()%5);
}
return NULL;
}
int main() {
srand(time(NULL));
int k;
sem_init(&lock, 0, 1);
sem_init(&fullItems, 0, 0);
printf("Enter the number of producers-->"); scanf("%d", &PROD_NUM);
products = (pthread_t*) malloc(PROD_NUM*sizeof(pthread_t)); printf("Enter the number of consumers-->");
scanf("%d", &CON_NUM);
cons = (pthread_t*) malloc(CON_NUM*sizeof(pthread_t)); printf("Enter the number of elements in the buffer-->"); scanf("%d", &BUFF_NUM);
buff = (int*)malloc(BUFF_NUM*sizeof(int)); sem_init(&emptyItems, 0, BUFF_NUM);
for (int i =0; i
{
k = pthread_create(products+i, NULL, &PRODUCER, NULL); if (k) {
printf("\n ERROR: return code from pthread_create for producer number %d is %d\n",i+1, k);
exit(1);
}
else{


Скляр Богдан Юрійович ФБ-81

5
printf("Successfully created producer %d\n",i+1);
}
}
for (int i =0; i{
k = pthread_create(cons+i, NULL, &CONSUMER, NULL); if (k) {
printf("\n ERROR: return code from pthread_create for consumer number %d is %d\n",i+1, k);
exit(1);
}else{
printf("Successfully created consumer %d\n",i+1);
}
}
for (int i =0; i
for (int i =0; iAir-Sklar:Desktop sklyarbogdan$ gcc -o lab81 lab8.cpp -pthread Air-Sklar:Desktop sklyarbogdan$ ./lab81
Enter the number of producers-->3
Enter the number of consumers-->3
Enter the number of elements in the buffer-->5
Successfully created producer 1
Successfully created producer 2
producer no. 1 produced item 652
Successfully created producer 3
producer no. 3 produced item 938
Successfully created consumer 1
producer no. 2 produced item 624
Successfully created consumer 2
Buffer--> 652 938 624
Consumer no. 1 consumed item 624
Buffer--> 652 938 624

2. Продовженння розминки
Air-Sklar:Desktop sklyarbogdan$ touch lab82.cpp Air-Sklar:Desktop sklyarbogdan$ cat lab82.cpp #include
#include
#include

#include
#include
#include

pthread_cond_t not_empty, not_full; pthread_mutex_t lock; int *buff, buffPos = -1;
pthread_t *cons;
pthread_t *products;
int prod_N, con_N, buff_N;
int count = 0;
int produce(pthread_t self){
int i =0;


Скляр Богдан Юрійович ФБ-81

6
int item = 1+rand()%1000;
while(!pthread_equal(*(products+i),self) && i< prod_N) {i++;} printf("Producer no. %d produced item %d \n", i+1, item); return item;
}
void append(int item) {
++buffPos;
*(buff + buffPos) = item;
count++;
}
void* producer(void * data){
while(1)
{
int item = produce(pthread_self());
pthread_mutex_lock(&lock);
while (count == buff_N) {pthread_cond_wait(¬_full, &lock); } append(item);
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&lock);
sleep(1+rand()%3);
}
return NULL;
}
void receive(pthread_t self){
int i =0;
int item = *(buff+buffPos);
while(!pthread_equal(*(cons+i),self) && i< con_N) {i++;} printf("Buffer: ");
for (int i =0; i<=buffPos; ++i) printf("%d ", *(buff+i)); printf("\nConsumer no. %d consumed item %d\n", i+1, item); --buffPos;
count--;
}
void* consumer(void * data) {
while(1)
{
pthread_mutex_lock(&lock);
while(count == 0){ pthread_cond_wait(¬_empty, &lock); }
receive(pthread_self());
pthread_cond_signal(¬_full);
pthread_mutex_unlock(&lock);
sleep(1+rand()%5);
}
return NULL;
}
int main() {
srand(time(NULL));
int rc;
printf("Enter the number of Producers:"); scanf("%d", &prod_N);
products = (pthread_t*) malloc(prod_N*sizeof(pthread_t)); printf("Enter the number of Consumers:");
scanf("%d", &con_N);
cons = (pthread_t*) malloc(con_N*sizeof(pthread_t)); printf("Enter the number of elements in the buffer:"); scanf("%d", &buff_N);


Скляр Богдан Юрійович ФБ-81

7
buff = (int*)malloc(buff_N*sizeof(int)); for (int i =0; i
{
rc = pthread_create(products+i, NULL, &producer, NULL); if (rc) {
printf("\n ERROR: return code from pthread_create for producer number %d is %d\n",i+1, rc);
exit(1);
}else{
printf("Successfully created producer %d\n",i+1);
}
}
for (int i =0; i{
rc = pthread_create(cons+i, NULL, &consumer, NULL); if (rc) {
printf("\n ERROR: return code from pthread_create for consumer number %d is %d\n",i+1, rc);
exit(1);
}else{
printf("Successfully created consumer %d\n",i+1);
}
}
for (int i =0; i
Air-Sklar:Desktop sklyarbogdan$ gcc -o lab82 lab82.cpp -pthread
Enter the number of Producers:4
Enter the number of Consumers:4
Enter the number of elements in the buffer:5 Successfully created producer 1
Producer no. 1 produced item 129
Successfully created producer 2
Successfully created producer 3
Successfully created producer 4
Producer no. 2 produced item 172
Successfully created consumer 1
Successfully created consumer 2
Successfully created consumer 3
Successfully created consumer 4
Producer no. 3 produced item 181
Buffer: 129 172 181
Consumer no. 1 consumed item 172
Buffer: 129 172
Consumer no. 2 consumed item 172
Buffer: 129
Consumer no. 3 consumed item 172
Producer no. 4 produced item 823
Buffer: 823
Consumer no. 4 consumed item 823
Producer no. 2 produced item 747
Producer no. 3 produced item 693
Buffer: 747 693
Consumer no. 4 consumed item 747
^C


Скляр Богдан Юрійович ФБ-81

8
3. Індивідуальне завдання
1(а).
Air-Sklar:Desktop sklyarbogdan$ touch lab8a.cpp Air-Sklar:Desktop sklyarbogdan$ cat lab8a.cpp #include
#include
#include

double pi = 0.;
pthread_mutex_t mut;
struct lim{ int from, to; };
void* cal(void* value){
lim* lims = (lim*) value;
double sum = 0;
for(int i = lims->from; i < lims->to; i++){ double first = 1 / (double)(4*i + 1); double second = 1 / (double)(4*i + 3);
// printf("%f\n", first);
sum += first - second;
}
pthread_mutex_lock(&mut);
pi += sum;
pthread_mutex_unlock(&mut);
}

int main(int argc, char** argv){
int iterations = atoi(argv[1]);
int numOfThreads = atoi(argv[2]);
lim lims[numOfThreads];
pthread_t threads[numOfThreads];
for (int i = 0; i < numOfThreads; i++){
lims[i].from = i*iterations/numOfThreads;
lims[i].to = (i+1)*iterations/numOfThreads;
pthread_create(&threads[i], NULL, cal, (void*) &lims[i]);
}
if (iterations % numOfThreads != 0) { lim lims2;
lims2.from = iterations - (iterations % numOfThreads); lims2.to = iterations;
pthread_t tid;
pthread_create(&tid, NULL, cal, (void*) &lims2); pthread_join(tid, NULL);
}
for (int i = 0; i < numOfThreads; ++i)
{
pthread_join(threads[i], NULL);
}
pi = pi * 4;


Скляр Богдан Юрійович ФБ-81

9
printf("%lf\n", pi); }
Air-Sklar:Desktop sklyarbogdan$ g++ -o lab8a lab8a.cpp -pthread Air-Sklar:Desktop sklyarbogdan$ ./lab8a
3.14
1(б).
Air-Sklar:Desktop sklyarbogdan$ touch lab83.cpp Air-Sklar:Desktop sklyarbogdan$ cat lab83.cpp #include
#include
#include

#include
#include

#include
#include
#include
#include
double pi = 0.;
int stop = 0;
pthread_mutex_t mut;
struct lim{
int from, to;
};
void stopHandler(int i){
stop = 1;
}
void* cal(void* value){
lim* lims = (lim*) value;
double sum = 0; for(int i = lims->from; i < lims->to; i++){ double first = 1 / (double)(4*i + 1);
double second = 1 / (double)(4*i + 3); sum += first - second; }
pthread_mutex_lock(&mut);
pi += sum;
pthread_mutex_unlock(&mut);
}

int main(){
int current_num = 0;
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = stopHandler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGINT);
sigaction(SIGINT, &act, 0);


Скляр Богдан Юрійович ФБ-81

10
while(!stop){
int numOfThreads = 5;
pthread_t tids[numOfThreads];
lim* lims;
for (int i = 0; i < numOfThreads; i++)
{
lims = new lim;
lims->from = currentNum;
lims->to = current_num + 1000;
pthread_create(&tids[i], NULL, cal, (void*)lims);
current_num += 1000;
}
for (int i = 0; i < numOfThreads; ++i)
{
pthread_join(tids[i], NULL);
}
}
pi = pi * 4; printf("%lf\n", pi); }
Air-Sklar:Desktop sklyarbogdan$ g++ -o lab83 lab83.cpp -pthread Air-Sklar:Desktop sklyarbogdan$ ./lab83 ^C3.141593

Висновки

Дана лабораторна робота дає змогу ознайомитися з основами роботи багатопотокових програм та їх розроблення з підтримкою засобів синхронізації. М'ютекс дозволяє потокам управляти доступом до даних. Семафор використовується для синхронізації потоків по діям, а також по даним. Використання таких засобів допомагає синхронізувати роботу потоків, та правильно розподіляти ресурси.


Скляр Богдан Юрійович ФБ-81

скачати

© Усі права захищені
написати до нас