diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..2590e02b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +update.sh +/lab4/src/build/ diff --git a/README.md b/README.md index c9f7285ee..1587d54e8 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Я написал программу: https://pastebin.com/YahFHx48. Я скомпилировал ее, и попытался ее выполнить, но получил ошибку "Invalid memory reference (SIGSEGV)". Я загуглил ошибку, но так и не понял, как исправить. -### Пример плохового вопроса: +### Пример плохого вопроса: Не работает: {тут код, который скопировали прямо в чат}. ### Время работы diff --git a/lab0/empty b/lab0/empty new file mode 100644 index 000000000..e69de29bb diff --git a/lab0/hello/newhello.c b/lab0/hello/newhello.c new file mode 100755 index 000000000..c71ae2565 --- /dev/null +++ b/lab0/hello/newhello.c @@ -0,0 +1,6 @@ +#include + +int main() +{ + printf("Hello World!\n"); +} \ No newline at end of file diff --git a/lab1/src/average.sh b/lab1/src/average.sh new file mode 100755 index 000000000..c03b34968 --- /dev/null +++ b/lab1/src/average.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +for (( a = 0; a < 150; a++ )) +do + echo $RANDOM +done > numbers.txt + +let average=0 +let cnt=0 + +while IFS= read -r number; +do + average=$((average + $number)) + cnt=$((cnt + 1)) +done < numbers.txt +echo $cnt +echo $((average / cnt)) \ No newline at end of file diff --git a/lab2/src/revert_string/main.c b/lab2/src/revert_string/main.c index 9f0e48135..75fce5966 100755 --- a/lab2/src/revert_string/main.c +++ b/lab2/src/revert_string/main.c @@ -4,21 +4,23 @@ #include "revert_string.h" -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - if (argc != 2) + if (argc != 3) { printf("Usage: %s string_to_revert\n", argv[0]); return -1; } - char *reverted_str = malloc(sizeof(char) * (strlen(argv[1]) + 1)); - strcpy(reverted_str, argv[1]); + unsigned arr_len = atoi(argv[1]); + char* reverted_str = malloc(sizeof(char) * (arr_len + 1)); + strcpy(reverted_str, argv[2]); - RevertString(reverted_str); + RevertString(reverted_str, arr_len); printf("Reverted: %s\n", reverted_str); free(reverted_str); return 0; } + diff --git a/lab2/src/revert_string/main.o b/lab2/src/revert_string/main.o new file mode 100644 index 000000000..c61ed6578 Binary files /dev/null and b/lab2/src/revert_string/main.o differ diff --git a/lab2/src/revert_string/revert.o b/lab2/src/revert_string/revert.o new file mode 100644 index 000000000..7cbff2f3d Binary files /dev/null and b/lab2/src/revert_string/revert.o differ diff --git a/lab2/src/revert_string/revert_string.c b/lab2/src/revert_string/revert_string.c index e257bbe26..57724c5db 100755 --- a/lab2/src/revert_string/revert_string.c +++ b/lab2/src/revert_string/revert_string.c @@ -1,7 +1,10 @@ #include "revert_string.h" -void RevertString(char *str) -{ - // your code here +void RevertString(char* str, const unsigned arr_len) { + unsigned medium_index = arr_len / 2; + for (int i = 0; i < medium_index; ++i) { + char temp = str[i]; + str[i] = str[arr_len - i - 1]; + str[arr_len - i - 1] = temp; + } } - diff --git a/lab2/src/revert_string/revert_string.h b/lab2/src/revert_string/revert_string.h index fc1492fb0..460d0a6b4 100755 --- a/lab2/src/revert_string/revert_string.h +++ b/lab2/src/revert_string/revert_string.h @@ -1,4 +1,4 @@ /* function to revert string */ -void RevertString(char *str); +void RevertString(char *, const unsigned); diff --git a/lab2/src/revert_string/shared/main.c b/lab2/src/revert_string/shared/main.c new file mode 100755 index 000000000..75fce5966 --- /dev/null +++ b/lab2/src/revert_string/shared/main.c @@ -0,0 +1,26 @@ +#include +#include +#include + +#include "revert_string.h" + +int main(int argc, char* argv[]) +{ + if (argc != 3) + { + printf("Usage: %s string_to_revert\n", argv[0]); + return -1; + } + + unsigned arr_len = atoi(argv[1]); + char* reverted_str = malloc(sizeof(char) * (arr_len + 1)); + strcpy(reverted_str, argv[2]); + + RevertString(reverted_str, arr_len); + + printf("Reverted: %s\n", reverted_str); + free(reverted_str); + return 0; +} + + diff --git a/lab2/src/revert_string/shared/main.o b/lab2/src/revert_string/shared/main.o new file mode 100644 index 000000000..d2060092b Binary files /dev/null and b/lab2/src/revert_string/shared/main.o differ diff --git a/lab2/src/revert_string/shared/make_shared.sh b/lab2/src/revert_string/shared/make_shared.sh new file mode 100644 index 000000000..c12fd17f8 --- /dev/null +++ b/lab2/src/revert_string/shared/make_shared.sh @@ -0,0 +1,6 @@ +#! +gcc -c -fPIC main.c -o main.o +gcc -c -fPIC revert_string.c -o revert_string.o +gcc -shared revert_string.o -o librevert_string.so +gcc main.o -L./ -lrevert_string -o reverted +LD_LIBRARY_PATH=$(pwd) ./reverted 9 123456789 \ No newline at end of file diff --git a/lab2/src/revert_string/shared/make_test.sh b/lab2/src/revert_string/shared/make_test.sh new file mode 100755 index 000000000..7be8fdf4b --- /dev/null +++ b/lab2/src/revert_string/shared/make_test.sh @@ -0,0 +1,5 @@ +#! +#Start this script after make_shared +gcc -c tests.c -L./ -o tests.o +gcc tests.o -L./ -lrevert_string -lcunit -o tests +LD_LIBRARY_PATH=$(pwd) ./tests \ No newline at end of file diff --git a/lab2/src/revert_string/shared/revert_string.c b/lab2/src/revert_string/shared/revert_string.c new file mode 100755 index 000000000..57724c5db --- /dev/null +++ b/lab2/src/revert_string/shared/revert_string.c @@ -0,0 +1,10 @@ +#include "revert_string.h" + +void RevertString(char* str, const unsigned arr_len) { + unsigned medium_index = arr_len / 2; + for (int i = 0; i < medium_index; ++i) { + char temp = str[i]; + str[i] = str[arr_len - i - 1]; + str[arr_len - i - 1] = temp; + } +} diff --git a/lab2/src/revert_string/shared/revert_string.h b/lab2/src/revert_string/shared/revert_string.h new file mode 100755 index 000000000..460d0a6b4 --- /dev/null +++ b/lab2/src/revert_string/shared/revert_string.h @@ -0,0 +1,4 @@ + +/* function to revert string */ +void RevertString(char *, const unsigned); + diff --git a/lab2/src/revert_string/shared/revert_string.o b/lab2/src/revert_string/shared/revert_string.o new file mode 100644 index 000000000..5d5a23a2e Binary files /dev/null and b/lab2/src/revert_string/shared/revert_string.o differ diff --git a/lab2/src/revert_string/shared/tests.c b/lab2/src/revert_string/shared/tests.c new file mode 100755 index 000000000..95c94396e --- /dev/null +++ b/lab2/src/revert_string/shared/tests.c @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "revert_string.h" + +void testRevertString(void) { + char simple_string[] = "Hello"; + char str_with_spaces[] = "String with spaces"; + char str_with_odd_chars_num[] = "abc"; + char str_with_even_chars_num[] = "abcd"; + + RevertString(simple_string, 5); + CU_ASSERT_STRING_EQUAL_FATAL(simple_string, "olleH"); + + RevertString(str_with_spaces, 18); + CU_ASSERT_STRING_EQUAL_FATAL(str_with_spaces, "secaps htiw gnirtS"); + + RevertString(str_with_odd_chars_num, 3); + CU_ASSERT_STRING_EQUAL_FATAL(str_with_odd_chars_num, "cba"); + + RevertString(str_with_even_chars_num, 4); + CU_ASSERT_STRING_EQUAL_FATAL(str_with_even_chars_num, "dcba"); +} + +int main() { + CU_pSuite pSuite = NULL; + + /* initialize the CUnit test registry */ + if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error(); + + /* add a suite to the registry */ + pSuite = CU_add_suite("Suite", NULL, NULL); + if (NULL == pSuite) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* add the tests to the suite */ + /* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */ + if ((NULL == CU_add_test(pSuite, "test of RevertString function", + testRevertString))) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* Run all tests using the CUnit Basic interface */ + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + CU_cleanup_registry(); + return CU_get_error(); +} diff --git a/lab2/src/revert_string/shared/tests.o b/lab2/src/revert_string/shared/tests.o new file mode 100644 index 000000000..19a0780ec Binary files /dev/null and b/lab2/src/revert_string/shared/tests.o differ diff --git a/lab2/src/swap/swap.c b/lab2/src/swap/swap.c index 38e97928c..9b7494f85 100755 --- a/lab2/src/swap/swap.c +++ b/lab2/src/swap/swap.c @@ -2,5 +2,7 @@ void Swap(char *left, char *right) { - // ваш код здесь + char temp = *left; + *left = *right; + *right = temp; } diff --git a/lab2/src/tests/tests.c b/lab2/src/tests/tests.c index a2431699c..95c94396e 100755 --- a/lab2/src/tests/tests.c +++ b/lab2/src/tests/tests.c @@ -10,16 +10,16 @@ void testRevertString(void) { char str_with_odd_chars_num[] = "abc"; char str_with_even_chars_num[] = "abcd"; - RevertString(simple_string); + RevertString(simple_string, 5); CU_ASSERT_STRING_EQUAL_FATAL(simple_string, "olleH"); - RevertString(str_with_spaces); + RevertString(str_with_spaces, 18); CU_ASSERT_STRING_EQUAL_FATAL(str_with_spaces, "secaps htiw gnirtS"); - RevertString(str_with_odd_chars_num); + RevertString(str_with_odd_chars_num, 3); CU_ASSERT_STRING_EQUAL_FATAL(str_with_odd_chars_num, "cba"); - RevertString(str_with_even_chars_num); + RevertString(str_with_even_chars_num, 4); CU_ASSERT_STRING_EQUAL_FATAL(str_with_even_chars_num, "dcba"); } diff --git a/lab2/text/lab2.md b/lab2/text/lab2.md index bf987c165..d678b9e4f 100755 --- a/lab2/text/lab2.md +++ b/lab2/text/lab2.md @@ -4,7 +4,7 @@ ### Необходимые знания -1. Как менять занчения переменных внутри функций в Си. +1. Как менять значения переменных внутри функций в Си. ### Задание В папке swap лежит 3 файла: swap.c, swap.h и main.c. Ваша задача закончить метод Swap в swap.c, так, чтобы он менял местами два символа. Скомпилировать программу. Если вы все сделали верно, то программа, которую вы собрали выведет "b a". diff --git a/lab3/src/MietOSSequentially b/lab3/src/MietOSSequentially new file mode 100755 index 000000000..52142771e Binary files /dev/null and b/lab3/src/MietOSSequentially differ diff --git a/lab3/src/find_min_max.c b/lab3/src/find_min_max.c index 6662a8fba..89f0a658c 100755 --- a/lab3/src/find_min_max.c +++ b/lab3/src/find_min_max.c @@ -2,11 +2,25 @@ #include -struct MinMax GetMinMax(int *array, unsigned int begin, unsigned int end) { +struct MinMax GetMinMax(int* array, unsigned int begin, const unsigned int end) { struct MinMax min_max; min_max.min = INT_MAX; min_max.max = INT_MIN; - // your code here - return min_max; + while(begin <= end) + { + /* If current element is greater than max */ + if(array[begin] > min_max.max) + { + min_max.max = array[begin]; + } + + /* If current element is smaller than min */ + if(array[begin] < min_max.min){ + min_max.min = array[begin]; + } + ++begin; + } + + return min_max; } diff --git a/lab3/src/find_min_max.h b/lab3/src/find_min_max.h index 07892028c..0957d80de 100755 --- a/lab3/src/find_min_max.h +++ b/lab3/src/find_min_max.h @@ -3,6 +3,6 @@ #include "utils.h" -struct MinMax GetMinMax(int *array, unsigned int begin, unsigned int end); +struct MinMax GetMinMax(int*, unsigned int, const unsigned int); #endif diff --git a/lab3/src/first_task b/lab3/src/first_task new file mode 100755 index 000000000..436120de1 Binary files /dev/null and b/lab3/src/first_task differ diff --git a/lab3/src/first_task.sh b/lab3/src/first_task.sh new file mode 100755 index 000000000..d78027b4c --- /dev/null +++ b/lab3/src/first_task.sh @@ -0,0 +1,2 @@ +#!/bin/bash +gcc main.c find_min_max.c utils.c -o first_task diff --git a/lab3/src/main.c b/lab3/src/main.c new file mode 100644 index 000000000..4b5dee38d --- /dev/null +++ b/lab3/src/main.c @@ -0,0 +1,20 @@ +#include +#include +#include "find_min_max.h" +#include "utils.h" + +int main() { + const size_t size = 10; + + int* array = (int*)malloc(sizeof(int) * size); + GenerateArray(array, size, 12); + struct MinMax min_max = GetMinMax(array, 0, size-1); + + printf("Array is: "); + for(size_t i = 0; i < size; ++i){ + printf("%d, ", array[i]); + } + printf("\nMinimum is: %d, maximum is: %d", min_max.min, min_max.max); + + return 0; +} diff --git a/lab3/src/parallel_min_max.c b/lab3/src/parallel_min_max.c index acb35ec64..9bb6c7961 100755 --- a/lab3/src/parallel_min_max.c +++ b/lab3/src/parallel_min_max.c @@ -16,140 +16,205 @@ #include "utils.h" int main(int argc, char **argv) { - int seed = -1; - int array_size = -1; - int pnum = -1; - bool with_files = false; - - while (true) { - int current_optind = optind ? optind : 1; - - static struct option options[] = {{"seed", required_argument, 0, 0}, - {"array_size", required_argument, 0, 0}, - {"pnum", required_argument, 0, 0}, - {"by_files", no_argument, 0, 'f'}, - {0, 0, 0, 0}}; - - int option_index = 0; - int c = getopt_long(argc, argv, "f", options, &option_index); - - if (c == -1) break; - - switch (c) { - case 0: - switch (option_index) { - case 0: - seed = atoi(optarg); - // your code here - // error handling - break; - case 1: - array_size = atoi(optarg); - // your code here - // error handling - break; - case 2: - pnum = atoi(optarg); - // your code here - // error handling - break; - case 3: - with_files = true; - break; - - defalut: - printf("Index %d is out of options\n", option_index); + int seed = -1; + int array_size = -1; + int pnum = -1; + bool with_files = false; + + while (true) { + int current_optind = optind ? optind : 1; + + static struct option options[] = {{"seed", required_argument, 0, 0}, + {"array_size", required_argument, 0, 0}, + {"pnum", required_argument, 0, 0}, + {"by_files", no_argument, 0, 'f'}, + {0, 0, 0, 0}}; + + int option_index = 0; + int c = getopt_long(argc, argv, "f", options, &option_index); + + if (c == -1) break; + + switch (c) { + case 0: + switch (option_index) { + case 0: + seed = atoi(optarg); + if(seed<=0) + { + printf("seed is a positive number\n"); + return 1; + } + + break; + case 1: + array_size = atoi(optarg); + if (array_size<=0) + { + printf("array_size is a positive number\n"); + return 1; + } + break; + case 2: + pnum = atoi(optarg); + if(pnum<=0) + { + printf("pnum is a positive number\n"); + return 1; + } + break; + case 3: + with_files = true; + break; + + defalut: + printf("Index %d is out of options\n", option_index); + } + break; + case 'f': + with_files = true; + break; + + case '?': + break; + + default: + printf("getopt returned character code 0%o?\n", c); } - break; - case 'f': - with_files = true; - break; + } + + if (optind < argc) { + printf("Has at least one no option argument\n"); + return 1; + } + + if (seed == -1 || array_size == -1 || pnum == -1) { + printf("Usage: %s --seed \"num\" --array_size \"num\" --pnum \"num\" \n", + argv[0]); + return 1; + } + + int *array = (int*)malloc(sizeof(int) * array_size); + GenerateArray(array, array_size, seed); + int active_child_processes = 0; - case '?': - break; + struct timeval start_time; + gettimeofday(&start_time, NULL); - default: - printf("getopt returned character code 0%o?\n", c); + int step=array_size/pnum; + + FILE* fl; + int** pipefd; + if (with_files) { + fl=fopen("test.txt","w"); } - } - - if (optind < argc) { - printf("Has at least one no option argument\n"); - return 1; - } - - if (seed == -1 || array_size == -1 || pnum == -1) { - printf("Usage: %s --seed \"num\" --array_size \"num\" --pnum \"num\" \n", - argv[0]); - return 1; - } - - int *array = malloc(sizeof(int) * array_size); - GenerateArray(array, array_size, seed); - int active_child_processes = 0; - - struct timeval start_time; - gettimeofday(&start_time, NULL); - - for (int i = 0; i < pnum; i++) { - pid_t child_pid = fork(); - if (child_pid >= 0) { - // successful fork - active_child_processes += 1; - if (child_pid == 0) { - // child process - - // parallel somehow - - if (with_files) { - // use files here + else { + pipefd=(int**)malloc(sizeof(int*) * pnum); + } + + + for (int i = 0; i < pnum; i++) { + if (!with_files){ + pipefd[i]=(int*)malloc(sizeof(int)*2); + if (pipe(pipefd[i])==-1) { + printf("Pipe Failed"); + return 1; + } + } + pid_t child_pid = fork(); + if (child_pid >= 0) { + // successful fork + active_child_processes += 1; + if (child_pid == 0) { + printf("Pipe was created\n"); + + struct MinMax min_max_i; + // child process + if (i!=pnum-1){ + min_max_i=GetMinMax(array,i*step,(i+1)*step-1) ; + } + else{ + min_max_i=GetMinMax(array,i*step,array_size) ; + } // prallel somehow + + if (with_files) { + fwrite(&min_max_i.min,sizeof(int),1,fl); + fwrite(&min_max_i.max,sizeof(int),1,fl); + } else { + + write(pipefd[i][1],&min_max_i.min,sizeof(int)); + write(pipefd[i][1],&min_max_i.max,sizeof(int)); + + close(pipefd[i][1]); + } + return 0; + } + + } else { - // use pipe here + printf("Fork failed!\n"); + return 1; } - return 0; - } + } + if(with_files) + {fclose(fl); + fl=fopen("test.txt","r"); + } + + while (active_child_processes > 0) { + wait(NULL); - } else { - printf("Fork failed!\n"); - return 1; + active_child_processes -= 1; } - } - while (active_child_processes > 0) { - // your code here + struct MinMax min_max; + min_max.min = INT_MAX; + min_max.max = INT_MIN; - active_child_processes -= 1; - } + for (int i = 0; i < pnum; i++) { + int min = INT_MAX; + int max = INT_MIN; - struct MinMax min_max; - min_max.min = INT_MAX; - min_max.max = INT_MIN; + if (with_files) { // read from files - for (int i = 0; i < pnum; i++) { - int min = INT_MAX; - int max = INT_MIN; - if (with_files) { - // read from files - } else { - // read from pipes + fread(&min,sizeof(int),1,fl); + fread(&max,sizeof(int),1,fl); + + } else { + //close(pipefd[i][1]); + + read(pipefd[i][0],&min,sizeof(int)); + read(pipefd[i][0],&max,sizeof(int)); + + close(pipefd[i][0]); + + free(pipefd[i]) ; + } + + + if (min < min_max.min) min_max.min = min; + if (max > min_max.max) min_max.max = max; } - if (min < min_max.min) min_max.min = min; - if (max > min_max.max) min_max.max = max; - } + if (with_files) { + fclose(fl); + } + else { + free(pipefd); + } - struct timeval finish_time; - gettimeofday(&finish_time, NULL); + struct timeval finish_time; + gettimeofday(&finish_time, NULL); - double elapsed_time = (finish_time.tv_sec - start_time.tv_sec) * 1000.0; - elapsed_time += (finish_time.tv_usec - start_time.tv_usec) / 1000.0; + double elapsed_time = (finish_time.tv_sec - start_time.tv_sec) * 1000.0; + elapsed_time += (finish_time.tv_usec - start_time.tv_usec) / 1000.0; - free(array); + free(array); - printf("Min: %d\n", min_max.min); - printf("Max: %d\n", min_max.max); - printf("Elapsed time: %fms\n", elapsed_time); - fflush(NULL); - return 0; -} + printf("Min: %d\n", min_max.min); + printf("Max: %d\n", min_max.max); + printf("Elapsed time: %fms\n", elapsed_time); + fflush(NULL); + return 0; +} \ No newline at end of file diff --git a/lab3/src/run_exec.c b/lab3/src/run_exec.c new file mode 100644 index 000000000..8d27a51f7 --- /dev/null +++ b/lab3/src/run_exec.c @@ -0,0 +1,11 @@ +// +// Created by sergeyampo on 24.04.2020. +// +#include + +int main(){ + printf("Now we're running sequential_min_max in exec mode!\n"); + execlp("MietOSSequentially", "MietOSSequentially", 100500, 1234, 100500); + + return 0; +} \ No newline at end of file diff --git a/lab3/src/sequential_min_max b/lab3/src/sequential_min_max new file mode 100755 index 000000000..bbcaed455 Binary files /dev/null and b/lab3/src/sequential_min_max differ diff --git a/lab3/src/sequential_min_max.c b/lab3/src/sequential_min_max.c index e6bd2d866..be2c31de6 100755 --- a/lab3/src/sequential_min_max.c +++ b/lab3/src/sequential_min_max.c @@ -24,7 +24,7 @@ int main(int argc, char **argv) { int *array = malloc(array_size * sizeof(int)); GenerateArray(array, array_size, seed); - struct MinMax min_max = GetMinMax(array, 0, array_size); + struct MinMax min_max = GetMinMax(array, 0, array_size-1); free(array); printf("min: %d\n", min_max.min); diff --git a/lab3/src/utils.c b/lab3/src/utils.c index d1650659d..b07989e58 100755 --- a/lab3/src/utils.c +++ b/lab3/src/utils.c @@ -2,7 +2,7 @@ #include #include -void GenerateArray(int *array, unsigned int array_size, unsigned int seed) { +void GenerateArray(int* array, unsigned int array_size, unsigned int seed) { srand(seed); for (int i = 0; i < array_size; i++) { array[i] = rand(); diff --git a/lab4/src/CMakeLists.txt b/lab4/src/CMakeLists.txt new file mode 100644 index 000000000..9a591b71c --- /dev/null +++ b/lab4/src/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.1) +project(OSLAB4 LANGUAGES C) + +add_executable(parallel_min_max parallel_min_max.c utils.c find_min_max.c) + +target_include_directories(parallel_min_max PUBLIC ./) + +set_target_properties(parallel_min_max PROPERTIES LINKER_LANGUAGE C) \ No newline at end of file diff --git a/lab4/src/build&run_parallel_min_max.sh b/lab4/src/build&run_parallel_min_max.sh new file mode 100644 index 000000000..0fd2b52cd --- /dev/null +++ b/lab4/src/build&run_parallel_min_max.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/parallel_min_max --seed 34434 --array_size 34454545 --pnum 4 --timeout 2 -f \ No newline at end of file diff --git a/lab4/src/find_min_max.c b/lab4/src/find_min_max.c new file mode 100755 index 000000000..89f0a658c --- /dev/null +++ b/lab4/src/find_min_max.c @@ -0,0 +1,26 @@ +#include "find_min_max.h" + +#include + +struct MinMax GetMinMax(int* array, unsigned int begin, const unsigned int end) { + struct MinMax min_max; + min_max.min = INT_MAX; + min_max.max = INT_MIN; + + while(begin <= end) + { + /* If current element is greater than max */ + if(array[begin] > min_max.max) + { + min_max.max = array[begin]; + } + + /* If current element is smaller than min */ + if(array[begin] < min_max.min){ + min_max.min = array[begin]; + } + ++begin; + } + + return min_max; +} diff --git a/lab4/src/find_min_max.h b/lab4/src/find_min_max.h new file mode 100755 index 000000000..0957d80de --- /dev/null +++ b/lab4/src/find_min_max.h @@ -0,0 +1,8 @@ +#ifndef FIND_MIN_MAX_H +#define FIND_MIN_MAX_H + +#include "utils.h" + +struct MinMax GetMinMax(int*, unsigned int, const unsigned int); + +#endif diff --git a/lab4/src/parallel_min_max.c b/lab4/src/parallel_min_max.c new file mode 100755 index 000000000..94281c542 --- /dev/null +++ b/lab4/src/parallel_min_max.c @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "find_min_max.h" +#include "utils.h" + +bool is_timed_out = false; + +void sig_handler(int signo) { + is_timed_out = true; + printf("The time is out!\n"); +} + +int kill_children(pid_t* pids, const size_t* size){ + for(size_t i = 0; i < size; ++i) { + kill(pids[i], 9); + } + printf("All child processes were killed!"); + return 1; +} + +int main(int argc, char **argv) { + int seed = -1; + int array_size = -1; + int pnum = -1; + int timeout = -1; + bool with_files = false; + + while (true) { + int current_optind = optind ? optind : 1; + + static struct option options[] = {{"seed", required_argument, 0, 0}, + {"array_size", required_argument, 0, 0}, + {"pnum", required_argument, 0, 0}, + {"timeout", required_argument, 0, 0}, ///TODO change to optional + {"by_files", no_argument, 0, 'f'}, + {0, 0, 0, 0}}; + + int option_index = 0; + int c = getopt_long(argc, argv, "f", options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 0: + switch (option_index) { + case 0: + seed = atoi(optarg); + if (seed <= 0) { + printf("seed is a positive number\n"); + return 1; + } + + break; + case 1: + array_size = atoi(optarg); + if (array_size <= 0) { + printf("array_size is a positive number\n"); + return 1; + } + break; + case 2: + pnum = atoi(optarg); + if (pnum <= 0) { + printf("pnum is a positive number\n"); + return 1; + } + break; + + case 3: + timeout = atoi(optarg); + if (timeout <= 0) { + printf("timeout is a positive number\n"); + return 1; + } + break; + + case 4: + with_files = true; + break; + + default: + printf("Index %d is out of options\n", option_index); + break; + } + break; + case 'f': + with_files = true; + break; + + case '?': + break; + + default: + printf("getopt returned character code 0%o?\n", c); + } + } + + if (optind < argc) { + printf("Has at least one no option argument\n"); + return 1; + } + + if (seed == -1 || array_size == -1 || pnum == -1) { + printf("Usage: %s --seed \"num\" --array_size \"num\" --pnum \"num\ --timeout \"num\" \n", + argv[0]); + return 1; + } + + int *array = (int *) malloc(sizeof(int) * array_size); + GenerateArray(array, array_size, seed); + int active_child_processes = 0; + + struct timeval start_time; + gettimeofday(&start_time, NULL); + + int step = array_size / pnum; + + FILE *fl; + int **pipefd; + if (with_files) { + fl = fopen("test.txt", "w"); + } else { + pipefd = (int **) malloc(sizeof(int *) * pnum); + } + + pid_t children[pnum]; + + //send signal to ourself when the time is out + signal(SIGALRM, sig_handler); + alarm(timeout); + + for (int i = 0; i < pnum; i++) { + if (!with_files) { + pipefd[i] = (int *) malloc(sizeof(int) * 2); + if (pipe(pipefd[i]) == -1) { + printf("Pipe Failed"); + return 1; + } + } + + pid_t child_pid = fork(); + children[i] = child_pid; + if (child_pid >= 0) { + // successful fork + active_child_processes += 1; + if (child_pid == 0) { //CHILD + printf("Pipe was created\n"); + + struct MinMax min_max_i; + // child process + if (i != pnum - 1) { + min_max_i = GetMinMax(array, i * step, (i + 1) * step - 1); + } else { + min_max_i = GetMinMax(array, i * step, array_size); + } // prallel somehow + + if (with_files) { + fwrite(&min_max_i.min, sizeof(int), 1, fl); + fwrite(&min_max_i.max, sizeof(int), 1, fl); + } else { + + write(pipefd[i][1], &min_max_i.min, sizeof(int)); + write(pipefd[i][1], &min_max_i.max, sizeof(int)); + + close(pipefd[i][1]); + } + return 0; + } +//PARENT + + } else { + printf("Fork failed!\n"); + return 1; + } + } + if (with_files) { + fclose(fl); + fl = fopen("test.txt", "r"); + } + + int status_pid; + + while (active_child_processes > 0) { + if(is_timed_out) + return kill_children(children, pnum); + + if (waitpid(-1, &status_pid, WNOHANG) > 0) { //If any child has died + active_child_processes -= 1; + } + + } + + struct MinMax min_max; + min_max.min = INT_MAX; + min_max.max = INT_MIN; + + for (int i = 0; i < pnum; i++) { + int min = INT_MAX; + int max = INT_MIN; + + if (with_files) { // read from files + + + fread(&min, sizeof(int), 1, fl); + fread(&max, sizeof(int), 1, fl); + + } else { + //close(pipefd[i][1]); + + read(pipefd[i][0], &min, sizeof(int)); + read(pipefd[i][0], &max, sizeof(int)); + + close(pipefd[i][0]); + + free(pipefd[i]); + } + + + if (min < min_max.min) min_max.min = min; + if (max > min_max.max) min_max.max = max; + } + + if (with_files) { + fclose(fl); + } else { + free(pipefd); + } + + struct timeval finish_time; + gettimeofday(&finish_time, NULL); + + double elapsed_time = (finish_time.tv_sec - start_time.tv_sec) * 1000.0; + elapsed_time += (finish_time.tv_usec - start_time.tv_usec) / 1000.0; + + free(array); + + printf("Min: %d\n", min_max.min); + printf("Max: %d\n", min_max.max); + printf("Elapsed time: %fms\n", elapsed_time); + fflush(NULL); + return 0; +} \ No newline at end of file diff --git a/lab4/src/parallel_sum.c b/lab4/src/parallel_sum.c deleted file mode 100755 index 66034d2c5..000000000 --- a/lab4/src/parallel_sum.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include - -#include - -struct SumArgs { - int *array; - int begin; - int end; -}; - -int Sum(const struct SumArgs *args) { - int sum = 0; - // TODO: your code here - return sum; -} - -void *ThreadSum(void *args) { - struct SumArgs *sum_args = (struct SumArgs *)args; - return (void *)(size_t)Sum(sum_args); -} - -int main(int argc, char **argv) { - /* - * TODO: - * threads_num by command line arguments - * array_size by command line arguments - * seed by command line arguments - */ - - uint32_t threads_num = 0; - uint32_t array_size = 0; - uint32_t seed = 0; - pthread_t threads[threads_num]; - - /* - * TODO: - * your code here - * Generate array here - */ - - int *array = malloc(sizeof(int) * array_size); - - struct SumArgs args[threads_num]; - for (uint32_t i = 0; i < threads_num; i++) { - if (pthread_create(&threads[i], NULL, ThreadSum, (void *)&args)) { - printf("Error: pthread_create failed!\n"); - return 1; - } - } - - int total_sum = 0; - for (uint32_t i = 0; i < threads_num; i++) { - int sum = 0; - pthread_join(threads[i], (void **)&sum); - total_sum += sum; - } - - free(array); - printf("Total: %d\n", total_sum); - return 0; -} diff --git a/lab4/src/parallel_sum/CMakeLists.txt b/lab4/src/parallel_sum/CMakeLists.txt new file mode 100644 index 000000000..7c5c4721e --- /dev/null +++ b/lab4/src/parallel_sum/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.1) +project(parallel_sum LANGUAGES C) + +add_executable(parallel_sum parallel_sum.c sum.c) + +find_package(Threads REQUIRED) + +target_link_libraries(parallel_sum ${CMAKE_THREAD_LIBS_INIT}) + +target_include_directories(parallel_sum PUBLIC ./) + +add_library(utils ../utils.c) + +target_include_directories(utils PUBLIC ../) + +target_link_libraries(parallel_sum utils) + +set_target_properties(parallel_sum PROPERTIES LINKER_LANGUAGE C) \ No newline at end of file diff --git a/lab4/src/parallel_sum/build&run_parallel_sum.sh b/lab4/src/parallel_sum/build&run_parallel_sum.sh new file mode 100644 index 000000000..c98b6db51 --- /dev/null +++ b/lab4/src/parallel_sum/build&run_parallel_sum.sh @@ -0,0 +1,11 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/parallel_sum --threads_num 1 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 2 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 3 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 4 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 5 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 6 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 7 --seed 34512 --array_size 60000000 +./build/parallel_sum --threads_num 8 --seed 34512 --array_size 60000000 \ No newline at end of file diff --git a/lab4/src/parallel_sum/parallel_sum.c b/lab4/src/parallel_sum/parallel_sum.c new file mode 100755 index 000000000..d4282595e --- /dev/null +++ b/lab4/src/parallel_sum/parallel_sum.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include "utils.h" +#include +#include +#include "sum.h" +#include + + +int main(int argc, char **argv) { + static struct option options[] = {{"seed", required_argument, 0, 0}, + {"array_size", required_argument, 0, 0}, + {"threads_num", required_argument, 0, 0}, + {0, 0, 0, 0}}; + + + int seed = -1; + int array_size = -1; + int threads_num = -1; + + int threads_amount = 0; + + while (true) { + int option_index = 0; + int c = getopt_long(argc, argv, "", options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 0: { + switch (option_index) { + case 0: { + seed = atoi(optarg); + if (seed < 0) { + printf("Seed must be a positive number or 0. Now seed is %d\n", seed); + return -1; + } + break; + } + + case 1: + array_size = atoi(optarg); + if (array_size < 0) { + printf("Array_size must be a positive number. Now array_size is %d\n", array_size); + return -1; + } + break; + + case 2: { + threads_num = atoi(optarg); + if (threads_num <= 0) { + printf("Threads_num must be 1 or more. Now threads_num is %d\n", threads_num); + return -1; + } + threads_amount = threads_num; + break; + } + } + break; + } + + case '?': + break; + + default: + printf("getopt returned character code 0%o?\n", c); + } + } + if (threads_num <= 0) { + printf("Threads_num must be 1 or more. Now threads_num is %d\n", threads_num); + return -1; + } + pthread_t threads[threads_num]; + + int *array = malloc(sizeof(int) * array_size); + GenerateArray(array, array_size, seed); + + struct timeval start_time; + gettimeofday(&start_time, NULL); + struct SumArgs args[threads_num]; + args[0].begin = 0; + + for (uint32_t i = 0; i < threads_num; i++) { + args[i].array = array; + if (i != 0) + args[i].begin = args[i - 1].end; + if (args[i].begin == array_size) + break; + if (i != threads_num - 1) { + args[i].end = (i + 1) * array_size / threads_num; + if (args[i].end > array_size) { + printf("%d %d\n", args[i].begin, args[i].end); + printf("SHIT!"); + return -1; + } + } else { + args[i].end = array_size; + } + if (pthread_create(&threads[i], NULL, ThreadSum, (void *) (args + i))) { + printf("Error: pthread_create failed!\n"); + return 1; + } + } + + long long int total_sum = 0; + for (uint32_t i = 0; i < threads_num; i++) { + long long int sum = 0; + pthread_join(threads[i], (void **) &sum); + total_sum += sum; + } + + struct timeval finish_time; + gettimeofday(&finish_time, NULL); + + double elapsed_time = (finish_time.tv_usec - start_time.tv_usec) / 1000.0; + free(array); + printf("Total: %lld\n", total_sum); + printf("It took %f milliseconds to find a sum for %d threads\n", elapsed_time, threads_amount); + return 0; +} \ No newline at end of file diff --git a/lab4/src/parallel_sum/sum.c b/lab4/src/parallel_sum/sum.c new file mode 100644 index 000000000..4d454b8f7 --- /dev/null +++ b/lab4/src/parallel_sum/sum.c @@ -0,0 +1,21 @@ +// +// Created by sergeyampo on 23.05.2020. +// + +#include "sum.h" + +long long int Sum(const struct SumArgs *args) { + long long int sum = 0; + // TODO: your code here + + for (int i = args->begin; i < args->end; i++) { + sum += args->array[i]; + } + + return sum; +} + +void *ThreadSum(void *args) { + struct SumArgs *sum_args = (struct SumArgs *) args; + return (void *) (long long int) Sum(sum_args); +} \ No newline at end of file diff --git a/lab4/src/parallel_sum/sum.h b/lab4/src/parallel_sum/sum.h new file mode 100644 index 000000000..47d52008d --- /dev/null +++ b/lab4/src/parallel_sum/sum.h @@ -0,0 +1,18 @@ +// +// Created by sergeyampo on 23.05.2020. +// + +#ifndef ZOMBIES_C_H +#define ZOMBIES_C_H + +struct SumArgs { + int *array; + int begin; + int end; +}; + +long long int Sum(const struct SumArgs *args); + +void *ThreadSum(void *args); + +#endif //ZOMBIES_C_H diff --git a/lab4/src/process_memory/CMakeLists.txt b/lab4/src/process_memory/CMakeLists.txt new file mode 100644 index 000000000..7695dc58f --- /dev/null +++ b/lab4/src/process_memory/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.1) +project(process_memory LANGUAGES C) + +add_executable(process_memory process_memory.c) \ No newline at end of file diff --git a/lab4/src/process_memory/build&run_process_memory.sh b/lab4/src/process_memory/build&run_process_memory.sh new file mode 100644 index 000000000..f2c211ff7 --- /dev/null +++ b/lab4/src/process_memory/build&run_process_memory.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/process_memory \ No newline at end of file diff --git a/lab4/src/process_memory.c b/lab4/src/process_memory/process_memory.c similarity index 77% rename from lab4/src/process_memory.c rename to lab4/src/process_memory/process_memory.c index 64b6b2b16..77e9921c9 100755 --- a/lab4/src/process_memory.c +++ b/lab4/src/process_memory/process_memory.c @@ -14,20 +14,20 @@ extern int etext, edata, end; /* Global variables for process memory */ char *cptr = "This message is output by the function showit()\n"; /* Static */ -char buffer1[25]; +char buffer1[25]; //Stack int showit(); /* Function prototype */ -main() { - int i = 0; /* Automatic variable */ +int main() { + int i = 0; /* Automatic variable */ - /* Printing addressing information */ - printf("\nAddress etext: %8X \n", &etext); - printf("Address edata: %8X \n", &edata); - printf("Address end : %8X \n", &end); + /* Printing addressing information */ + printf("\nAddress etext: %8X \n", &etext); + printf("Address edata: %8X \n", &edata); + printf("Address end : %8X \n", &end); - SHW_ADR("main", main); - SHW_ADR("showit", showit); - SHW_ADR("cptr", cptr); + SHW_ADR("main", main); + SHW_ADR("showit", showit); + SHW_ADR("cptr", cptr); SHW_ADR("buffer1", buffer1); SHW_ADR("i", i); strcpy(buffer1, "A demonstration\n"); /* Library function */ diff --git a/lab4/src/utils.c b/lab4/src/utils.c new file mode 100755 index 000000000..b07989e58 --- /dev/null +++ b/lab4/src/utils.c @@ -0,0 +1,10 @@ +#include "utils.h" + +#include +#include +void GenerateArray(int* array, unsigned int array_size, unsigned int seed) { + srand(seed); + for (int i = 0; i < array_size; i++) { + array[i] = rand(); + } +} diff --git a/lab4/src/utils.h b/lab4/src/utils.h new file mode 100755 index 000000000..f0c6c9456 --- /dev/null +++ b/lab4/src/utils.h @@ -0,0 +1,11 @@ +#ifndef UTILS_H +#define UTILS_H + +struct MinMax { + int min; + int max; +}; + +void GenerateArray(int *array, unsigned int array_size, unsigned int seed); + +#endif diff --git a/lab4/src/zombie-apocalypse/CMakeLists.txt b/lab4/src/zombie-apocalypse/CMakeLists.txt new file mode 100644 index 000000000..f4828f926 --- /dev/null +++ b/lab4/src/zombie-apocalypse/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.1) +project(zombies LANGUAGES C) + +add_executable(zombies zombie_spawner.c) \ No newline at end of file diff --git a/lab4/src/zombie-apocalypse/build&run_zombie_spawner.sh b/lab4/src/zombie-apocalypse/build&run_zombie_spawner.sh new file mode 100644 index 000000000..441f59dbf --- /dev/null +++ b/lab4/src/zombie-apocalypse/build&run_zombie_spawner.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/zombies \ No newline at end of file diff --git a/lab4/src/zombie-apocalypse/zombie_spawner.c b/lab4/src/zombie-apocalypse/zombie_spawner.c new file mode 100644 index 000000000..ad495f493 --- /dev/null +++ b/lab4/src/zombie-apocalypse/zombie_spawner.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include + +int main() { + pid_t child_pid; + printf("Started zombie apocalypse!"); + child_pid = fork(); + if (child_pid > 0) { + while (true); + } else { + exit(0); + } + + return 0; +} + + diff --git a/lab5/src/first/CMakeLists.txt b/lab5/src/first/CMakeLists.txt new file mode 100644 index 000000000..261420c0a --- /dev/null +++ b/lab5/src/first/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.1) +project(OSLAB5 LANGUAGES C) + +add_executable(mutex mutex.c) +add_executable(nomutex nomutex.c) + +find_package(Threads REQUIRED) + +target_link_libraries(mutex ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(nomutex ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/lab5/src/mutex.c b/lab5/src/first/mutex.c similarity index 77% rename from lab5/src/mutex.c rename to lab5/src/first/mutex.c index 4e86390db..716ec384c 100755 --- a/lab5/src/mutex.c +++ b/lab5/src/first/mutex.c @@ -25,14 +25,16 @@ pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; int main() { pthread_t thread1, thread2; - if (pthread_create(&thread1, NULL, (void *)do_one_thing, - (void *)&common) != 0) { + printf("Execute with mutex\n'"); + + if (pthread_create(&thread1, NULL, (void *) do_one_thing, + (void *) &common) != 0) { perror("pthread_create"); exit(1); } - if (pthread_create(&thread2, NULL, (void *)do_another_thing, - (void *)&common) != 0) { + if (pthread_create(&thread2, NULL, (void *) do_another_thing, + (void *) &common) != 0) { perror("pthread_create"); exit(1); } @@ -57,15 +59,14 @@ void do_one_thing(int *pnum_times) { unsigned long k; int work; for (i = 0; i < 50; i++) { - // pthread_mutex_lock(&mut); + pthread_mutex_lock(&mut); printf("doing one thing\n"); work = *pnum_times; printf("counter = %d\n", work); work++; /* increment, but not write */ - for (k = 0; k < 500000; k++) - ; /* long cycle */ + for (k = 0; k < 500000; k++); /* long cycle */ *pnum_times = work; /* write back */ - // pthread_mutex_unlock(&mut); + pthread_mutex_unlock(&mut); } } @@ -74,15 +75,14 @@ void do_another_thing(int *pnum_times) { unsigned long k; int work; for (i = 0; i < 50; i++) { - // pthread_mutex_lock(&mut); + pthread_mutex_lock(&mut); printf("doing another thing\n"); work = *pnum_times; printf("counter = %d\n", work); work++; /* increment, but not write */ - for (k = 0; k < 500000; k++) - ; /* long cycle */ + for (k = 0; k < 500000; k++); /* long cycle */ *pnum_times = work; /* write back */ - // pthread_mutex_unlock(&mut); + pthread_mutex_unlock(&mut); } } diff --git a/lab5/src/first/nomutex.c b/lab5/src/first/nomutex.c new file mode 100755 index 000000000..91fba8850 --- /dev/null +++ b/lab5/src/first/nomutex.c @@ -0,0 +1,87 @@ +/******************************************************** + * An example source module to accompany... + * + * "Using POSIX Threads: Programming with Pthreads" + * by Brad nichols, Dick Buttlar, Jackie Farrell + * O'Reilly & Associates, Inc. + * Modified by A.Kostin + ******************************************************** + * mutex.c + * + * Simple multi-threaded example with a mutex lock. + */ +#include +#include +#include +#include + +void do_one_thing(int *); +void do_another_thing(int *); +void do_wrap_up(int); +int common = 0; /* A shared variable for two threads */ +int r1 = 0, r2 = 0, r3 = 0; + +int main() { + pthread_t thread1, thread2; + + printf("Execute without mutex\n"); + + if (pthread_create(&thread1, NULL, (void *) do_one_thing, + (void *) &common) != 0) { + perror("pthread_create"); + exit(1); + } + + if (pthread_create(&thread2, NULL, (void *) do_another_thing, + (void *) &common) != 0) { + perror("pthread_create"); + exit(1); + } + + if (pthread_join(thread1, NULL) != 0) { + perror("pthread_join"); + exit(1); + } + + if (pthread_join(thread2, NULL) != 0) { + perror("pthread_join"); + exit(1); + } + + do_wrap_up(common); + + return 0; +} + +void do_one_thing(int *pnum_times) { + int i, j, x; + unsigned long k; + int work; + for (i = 0; i < 50; i++) { + printf("doing one thing\n"); + work = *pnum_times; + printf("counter = %d\n", work); + work++; /* increment, but not write */ + for (k = 0; k < 500000; k++); /* long cycle */ + *pnum_times = work; /* write back */ + } +} + +void do_another_thing(int *pnum_times) { + int i, j, x; + unsigned long k; + int work; + for (i = 0; i < 50; i++) { + printf("doing another thing\n"); + work = *pnum_times; + printf("counter = %d\n", work); + work++; /* increment, but not write */ + for (k = 0; k < 500000; k++); /* long cycle */ + *pnum_times = work; /* write back */ + } +} + +void do_wrap_up(int counter) { + int total; + printf("All done, counter = %d\n", counter); +} diff --git a/lab5/src/first/run.sh b/lab5/src/first/run.sh new file mode 100644 index 000000000..7d758f2d5 --- /dev/null +++ b/lab5/src/first/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/mutex +./build/nomutex \ No newline at end of file diff --git a/lab5/src/second/CMakeLists.txt b/lab5/src/second/CMakeLists.txt new file mode 100644 index 000000000..7d18030fa --- /dev/null +++ b/lab5/src/second/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.1) +project(OSLAB5 LANGUAGES C) + +add_executable(factorial factorial.c) + +find_package(Threads REQUIRED) + +target_link_libraries(factorial ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/lab5/src/second/factorial.c b/lab5/src/second/factorial.c new file mode 100644 index 000000000..e926f23ef --- /dev/null +++ b/lab5/src/second/factorial.c @@ -0,0 +1,114 @@ +// +// Created by sergeyampo on 01.06.2020. +// +#include +#include +#include +#include +#include + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +int factorial_value = 1; + +typedef struct { + int begin; + int end; +} FactorialPart; + +void *calculate_factorial(void *args) { + + FactorialPart *f_part = (FactorialPart *) args; + int res = 1; + + for (int i = f_part->begin; i < f_part->end; i++) + res *= (i + 1); + + pthread_mutex_lock(&mutex); + factorial_value *= res; + pthread_mutex_unlock(&mutex); + +} + +int main(int argc, char **argv) { + + uint32_t k = -1; + uint32_t threads_num = -1; + uint32_t mod = -1; + + while (1) { + static struct option options[] = {{"k", required_argument, 0, 0}, + {"pnum", required_argument, 0, 0}, + {"mod", required_argument, 0, 0}, + {0, 0, 0, 0}}; + + int option_index = 0; + int c = getopt_long(argc, argv, "?", options, &option_index); + + if (c == -1) break; + + switch (c) { + case 0: + switch (option_index) { + case 0:k = atoi(optarg); + if (k < 0) { + printf("Number must be positive\n"); + return 1; + } + break; + case 1:threads_num = atoi(optarg); + if (threads_num < 0) { + printf("Threads number must be positive\n"); + return 1; + } + break; + case 2:mod = atoi(optarg); + if (mod < 0) { + printf("Mod number must be positive\n"); + return 1; + } + break; + } + break; + + case '?':break; + + default:printf("getopt returned character code 0%o?\n", c); + } + } + + if (optind < argc) { + printf("Has at least one no option argument\n"); + return 1; + } + + if (k == -1 || threads_num == -1 || mod == -1) { + printf("Usage: %s --k \"num\" --pnum \"num\" --mod \"num\" \n", + argv[0]); + return 1; + } + + int step = k > threads_num ? (k / threads_num) : 1; + pthread_mutex_init(&mutex, NULL); + pthread_t threads[threads_num]; + FactorialPart factorial_parts[threads_num]; + + for (uint32_t i = 0; i < threads_num; i++) { + factorial_parts[i].begin = step * i; + factorial_parts[i].end = (i + 1) * step; + // printf("Begin %d, end %d\n", (step * i),((i + 1) * step)); + if (pthread_create(&threads[i], NULL, calculate_factorial, (void *) &factorial_parts[i])) { + perror("\nERROR CREATE THREAD\n"); + return 1; + } + } + + for (uint32_t i = 0; i < threads_num; i++) { + pthread_join(threads[i], NULL); + } + pthread_mutex_destroy(&mutex); + printf("The factorial of %i equals %i.\n", k, factorial_value); + printf("The factorial of %i with module %i equals %i.\n", k, mod, factorial_value % mod); + printf("-------------------------------------------\n"); + + return 0; +} diff --git a/lab5/src/second/run.sh b/lab5/src/second/run.sh new file mode 100644 index 000000000..55e40ca74 --- /dev/null +++ b/lab5/src/second/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/factorial --k 8 --pnum 8 --mod 2 \ No newline at end of file diff --git a/lab5/src/third/CMakeLists.txt b/lab5/src/third/CMakeLists.txt new file mode 100644 index 000000000..11529c38a --- /dev/null +++ b/lab5/src/third/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.1) +project(OSLAB5 LANGUAGES C) + +add_executable(deadlock main.c) + +find_package(Threads REQUIRED) + +target_link_libraries(deadlock ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/lab5/src/third/main.c b/lab5/src/third/main.c new file mode 100644 index 000000000..316ba197b --- /dev/null +++ b/lab5/src/third/main.c @@ -0,0 +1,47 @@ +// +// Created by sergeyampo on 02.06.2020. +// +#include +#include +#include + +void get_res_lock(pthread_mutex_t *mutexes) { + pthread_mutex_lock(mutexes); + sleep(1); + printf("First thread locked first mutex and tried to lock second mutex\n"); + fflush(stdout); + pthread_mutex_lock(mutexes + 1); + pthread_mutex_unlock(mutexes); + pthread_mutex_unlock(mutexes + 1); +} + +void get_another_res(pthread_mutex_t *mutexes) { + pthread_mutex_lock(mutexes + 1); + sleep(1); + printf("Second thread locked second mutex and tried to lock first mutex\n"); + fflush(stdout); + pthread_mutex_lock(mutexes); + pthread_mutex_unlock(mutexes); + pthread_mutex_unlock(mutexes + 1); +} + +int main() { + pthread_mutex_t mutexes[2] = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}; + + pthread_t threads[2]; + if (pthread_create(threads, NULL, (void *) get_res_lock, (void *) mutexes)) { + perror("\nERROR CREATE THREAD\n"); + return 1; + } + + if (pthread_create(threads + 1, NULL, (void *) get_another_res, (void *) mutexes)) { + perror("\nERROR CREATE THREAD\n"); + return 1; + } + + for (int i = 0; i < 2; ++i) + pthread_join(threads[i], NULL); + + return 0; +} + diff --git a/lab5/src/third/run.sh b/lab5/src/third/run.sh new file mode 100644 index 000000000..71225a49f --- /dev/null +++ b/lab5/src/third/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/deadlock \ No newline at end of file diff --git a/lab7/src/CMakeLists.txt b/lab7/src/CMakeLists.txt new file mode 100644 index 000000000..e2b5da521 --- /dev/null +++ b/lab7/src/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.1) +project(Parallel_Factorial LANGUAGES C) + +add_subdirectory(./num_partition) +add_executable(Parallel_Factorial main.c) +target_link_libraries(Parallel_Factorial NumberPartition) + +find_package(Threads REQUIRED) +target_link_libraries(Parallel_Factorial ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/lab7/src/main.c b/lab7/src/main.c new file mode 100644 index 000000000..b5a6b70f2 --- /dev/null +++ b/lab7/src/main.c @@ -0,0 +1,72 @@ +// +// Created by sergeyampo on 17.06.2020. +// + +#include +#include +#include +#include +#include +#include +#include "./num_partition/number_partition.h" + + +const uint64_t factorial = 20; + +const uint64_t threads_amount = 4; + +const uint64_t multiply_by_interval(const struct Interval* interval) { + if (interval->begin == interval->end) + return interval->begin; + + uint64_t answer = interval->begin; + for (uint64_t i = interval->begin + 1; i <= interval->end; ++i) { + answer *= i; + } + + return answer; +} + +int main() { + if (factorial < 1 || threads_amount < 1) { + printf("Factorial and threads cannot be less that 1!"); + return 1; + } + + struct Interval* intervals = partition_num_to_intervals(&factorial, threads_amount); + uint64_t used_threads = threads_amount; + if (threads_amount > factorial) { + used_threads = factorial; + } + + clock_t start = clock(); + + pthread_t threads[used_threads]; + for (uint64_t i = 0; i < used_threads; ++i) { + if (pthread_create(&threads[i], NULL, &multiply_by_interval, intervals + i) != 0) { + printf("Error while creating a thread!"); + return 1; + } + } + + uint64_t parts[used_threads]; + uint64_t answer = 1; + + for (uint64_t i = 0; i < used_threads; ++i) { + void* part_res; + pthread_join(threads[i], &part_res); + parts[i] = (uint64_t)part_res; + answer *= parts[i]; + } + + clock_t end = clock(); + + printf("%" PRIu64 "\n", answer); + + printf("To calculate factorial %d by %d threads takes %F seconds\n", + factorial, + used_threads, + (float)(end - start) / CLOCKS_PER_SEC); + + return 0; +} diff --git a/lab7/src/num_partition/CMakeLists.txt b/lab7/src/num_partition/CMakeLists.txt new file mode 100644 index 000000000..d184b8c92 --- /dev/null +++ b/lab7/src/num_partition/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.1) +project(Parallel_Factorial LANGUAGES C) + +add_library(NumberPartition number_partition.c) +target_include_directories(NumberPartition PUBLIC ./) \ No newline at end of file diff --git a/lab7/src/num_partition/number_partition.c b/lab7/src/num_partition/number_partition.c new file mode 100644 index 000000000..cdde80816 --- /dev/null +++ b/lab7/src/num_partition/number_partition.c @@ -0,0 +1,34 @@ +// +// Created by sergeyampo on 17.06.2020. +// +#include +#include +#include "number_partition.h" + + +/** + * + * @param num - source number which we should partition + * @param intervals - amount of intervals. If intervals > num, we'll partition to num intervals. + * @return struct Interval* - pointer to the array of intervals, which size is intervals or num if intervals > num. + * @description For example num=7, intervals=3 = [1 ; 2], [3 ; 4] [5 ; 7]. num=3, intervals=4 [1 ; 1], [2 ; 2], [3 ; 3] + */ +struct Interval* partition_num_to_intervals(const uint64_t* num, uint64_t intervals) { + uint64_t parts = *num / intervals; + if (parts == 0) { + intervals = *num; + parts = 1; + } + struct Interval* output_intervals = (struct Interval*)malloc(sizeof(struct Interval) * intervals); + + uint64_t j = 1; + for (uint64_t i = 0; i < intervals - 1; ++i) { + output_intervals[i].begin = j; + output_intervals[i].end = j - 1 + parts; + j += parts; + } + output_intervals[intervals - 1].begin = j; + output_intervals[intervals - 1].end = *num; + + return output_intervals; +} diff --git a/lab7/src/num_partition/number_partition.h b/lab7/src/num_partition/number_partition.h new file mode 100644 index 000000000..cae8930b6 --- /dev/null +++ b/lab7/src/num_partition/number_partition.h @@ -0,0 +1,15 @@ +// +// Created by sergeyampo on 17.06.2020. +// + +#ifndef PARALLEL_FACTORIAL_SRC_NUMBER_PARTITION_H_ +#define PARALLEL_FACTORIAL_SRC_NUMBER_PARTITION_H_ + +struct Interval { + uint64_t begin; + uint64_t end; +}; + +struct Interval* partition_num_to_intervals(const uint64_t*, uint64_t); + +#endif //PARALLEL_FACTORIAL_SRC_NUMBER_PARTITION_H_ diff --git a/lab7/src/run.sh b/lab7/src/run.sh new file mode 100644 index 000000000..ecbf95e22 --- /dev/null +++ b/lab7/src/run.sh @@ -0,0 +1,4 @@ +#! +cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" -B./build -H./ +cmake --build ./build -- -j4 +./build/Parallel_Factorial \ No newline at end of file diff --git a/lab7/src/tcpclient.c b/lab7/src/tcpclient.c deleted file mode 100755 index 44fb2f48b..000000000 --- a/lab7/src/tcpclient.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define BUFSIZE 100 -#define SADDR struct sockaddr -#define SIZE sizeof(struct sockaddr_in) - -int main(int argc, char *argv[]) { - int fd; - int nread; - char buf[BUFSIZE]; - struct sockaddr_in servaddr; - if (argc < 3) { - printf("Too few arguments \n"); - exit(1); - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket creating"); - exit(1); - } - - memset(&servaddr, 0, SIZE); - servaddr.sin_family = AF_INET; - - if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) { - perror("bad address"); - exit(1); - } - - servaddr.sin_port = htons(atoi(argv[2])); - - if (connect(fd, (SADDR *)&servaddr, SIZE) < 0) { - perror("connect"); - exit(1); - } - - write(1, "Input message to send\n", 22); - while ((nread = read(0, buf, BUFSIZE)) > 0) { - if (write(fd, buf, nread) < 0) { - perror("write"); - exit(1); - } - } - - close(fd); - exit(0); -} diff --git a/lab7/src/tcpserver.c b/lab7/src/tcpserver.c deleted file mode 100755 index 01489864e..000000000 --- a/lab7/src/tcpserver.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#define SERV_PORT 10050 -#define BUFSIZE 100 -#define SADDR struct sockaddr - -int main() { - const size_t kSize = sizeof(struct sockaddr_in); - - int lfd, cfd; - int nread; - char buf[BUFSIZE]; - struct sockaddr_in servaddr; - struct sockaddr_in cliaddr; - - if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket"); - exit(1); - } - - memset(&servaddr, 0, kSize); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(SERV_PORT); - - if (bind(lfd, (SADDR *)&servaddr, kSize) < 0) { - perror("bind"); - exit(1); - } - - if (listen(lfd, 5) < 0) { - perror("listen"); - exit(1); - } - - while (1) { - unsigned int clilen = kSize; - - if ((cfd = accept(lfd, (SADDR *)&cliaddr, &clilen)) < 0) { - perror("accept"); - exit(1); - } - printf("connection established\n"); - - while ((nread = read(cfd, buf, BUFSIZE)) > 0) { - write(1, &buf, nread); - } - - if (nread == -1) { - perror("read"); - exit(1); - } - close(cfd); - } -} diff --git a/lab7/src/udpclient.c b/lab7/src/udpclient.c deleted file mode 100755 index 2c02b8d72..000000000 --- a/lab7/src/udpclient.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define SERV_PORT 20001 -#define BUFSIZE 1024 -#define SADDR struct sockaddr -#define SLEN sizeof(struct sockaddr_in) - -int main(int argc, char **argv) { - int sockfd, n; - char sendline[BUFSIZE], recvline[BUFSIZE + 1]; - struct sockaddr_in servaddr; - struct sockaddr_in cliaddr; - - if (argc != 2) { - printf("usage: client \n"); - exit(1); - } - - memset(&servaddr, 0, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(SERV_PORT); - - if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) { - perror("inet_pton problem"); - exit(1); - } - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket problem"); - exit(1); - } - - write(1, "Enter string\n", 13); - - while ((n = read(0, sendline, BUFSIZE)) > 0) { - if (sendto(sockfd, sendline, n, 0, (SADDR *)&servaddr, SLEN) == -1) { - perror("sendto problem"); - exit(1); - } - - if (recvfrom(sockfd, recvline, BUFSIZE, 0, NULL, NULL) == -1) { - perror("recvfrom problem"); - exit(1); - } - - printf("REPLY FROM SERVER= %s\n", recvline); - } - close(sockfd); -} diff --git a/lab7/src/udpserver.c b/lab7/src/udpserver.c deleted file mode 100755 index 2c7f2dd80..000000000 --- a/lab7/src/udpserver.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SERV_PORT 20001 -#define BUFSIZE 1024 -#define SADDR struct sockaddr -#define SLEN sizeof(struct sockaddr_in) - -int main() { - int sockfd, n; - char mesg[BUFSIZE], ipadr[16]; - struct sockaddr_in servaddr; - struct sockaddr_in cliaddr; - - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket problem"); - exit(1); - } - - memset(&servaddr, 0, SLEN); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(SERV_PORT); - - if (bind(sockfd, (SADDR *)&servaddr, SLEN) < 0) { - perror("bind problem"); - exit(1); - } - printf("SERVER starts...\n"); - - while (1) { - unsigned int len = SLEN; - - if ((n = recvfrom(sockfd, mesg, BUFSIZE, 0, (SADDR *)&cliaddr, &len)) < 0) { - perror("recvfrom"); - exit(1); - } - mesg[n] = 0; - - printf("REQUEST %s FROM %s : %d\n", mesg, - inet_ntop(AF_INET, (void *)&cliaddr.sin_addr.s_addr, ipadr, 16), - ntohs(cliaddr.sin_port)); - - if (sendto(sockfd, mesg, n, 0, (SADDR *)&cliaddr, len) < 0) { - perror("sendto"); - exit(1); - } - } -} diff --git a/update.sh b/update.sh index db789f609..489060a6d 100755 --- a/update.sh +++ b/update.sh @@ -1,9 +1,4 @@ -sudo apt -y update -sudo apt -y upgrade -sudo apt -y install man -sudo apt -y install nano -sudo apt -y install clang-format -sudo apt -y install iputils-ping -sudo apt -y install gcc -sudo apt -y install dos2unix -sudo apt -y install libcunit1 libcunit1-doc libcunit1-dev \ No newline at end of file +!# +apt -y install clang-format +apt -y install iputils-ping +apt -y install libcunit1 libcunit1-doc libcunit1-dev \ No newline at end of file