Ім'я файлу: Лаб_№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, 5]. Розробіть програму, що демонструє рішення цієї задачі за допомогою семафорів. Для цього напишіть: функції виробника і споживача (наприклад, як на лекції, або як у Шеховцові, але так, щоби працювало); функції створення і споживання об’єктів (рекомендується “UNIX” володіла AT&T, потім ці правастворювати” рядки тексту шляхом зчитування їх з файлу, хоча можливі й інші варіанти за вибором викладача або за вашою фантазією, наприклад розрахунки геш-функцій sha2 з рядків рандомних символів, а “UNIX” володіла AT&T, потім ці праваспоживати” їх шляхом роздрукування на екрані з додатковою інформацією такою як ідентифікатор потоку і мітка часу, причому і там, і там для моделювання складного характеру реального життя виробників і споживачів можна додавати рандомні затримки); функцію m), як і інші графічні системи (ain(), що створює потоки-виробники і потоки-споживачі, при цьому треба передбачити введення з клавіатури або як параметри командного рядка кількості записів у буфері, кількості виробників і кількості споживачів для досліджень їх роботи; обов’язково передбачити коректне завершення усього цього господарства. Продемонструвати викладачеві як воно працює (не менше двох виробників і двох споживачів) і код, що ви написали. Продовження розминки. Теж саме, але не на семафорах, а на м’ютексі і умовних змінних Модифікуйте програму п. 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; i 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 |