Advertisement
BorrowTheProgrammer

fedoruk_lab2_25

May 2nd, 2022
943
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.94 KB | None | 0 0
  1. #include <sys/wait.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <signal.h>
  7. #include <ctype.h>
  8. #include <pthread.h>
  9. #include <time.h>
  10.  
  11. #define BUF_SIZE 256
  12.  
  13. void reverse(char *);
  14. void changeCase(int, char *);
  15. void koi8er(char *);
  16. void swap(char *);
  17. void catchSignal(int);
  18. void commandToLowerCase(char *);
  19. int flag;
  20.  
  21. struct SHARED_DATA
  22. {
  23.     pthread_barrier_t barr[2];
  24.     char buf1[BUF_SIZE], buf2[BUF_SIZE];
  25.     int done, done1;
  26.     struct timespec waitStart0, waitEnd0,
  27.         waitStart1, waitEnd1, waitStart2, waitEnd2;
  28.     long globalEx0, globalEx1, globalEx2;
  29.     long globalWait0, globalWait1, globalWait2;
  30. };
  31.  
  32. typedef struct SHARED_DATA shared_data;
  33.  
  34. void printTimeData(shared_data *data)
  35. {
  36.     printf("\tОбщее время обработки текста первым потоком: %lld мкр. сек.\n", (long long)(data->globalEx0));
  37.     printf("\tОбщее время обработки текста вторым потоком: %lld мкр. сек.\n", (long long)(data->globalEx1));
  38.     printf("\tОбщее время обработки текста третьим потоком: %lld мкр. сек.\n", (long long)(data->globalEx2));
  39.     printf("\tОбщее время ожидания первого потока: %lld мкр. сек.\n", (long long)(data->globalWait0));
  40.     printf("\tОбщее время ожидания второго потока: %lld мкр. сек.\n", (long long)(data->globalWait1));
  41.     printf("\tОбщее время ожидания третього потока: %lld мкр. сек.\n", (long long)(data->globalWait2));
  42. }
  43.  
  44. void printWaitTimeData(shared_data *data)
  45. {
  46.     char denom[BUF_SIZE / 2];
  47.     memset(denom, '-', BUF_SIZE / 2);
  48.  
  49.     data->globalWait0 += (long)(data->waitEnd0.tv_nsec - data->waitStart0.tv_nsec) / 1000;
  50.     printf("\tВремя ожидания первого потока %lld мкр. сек. \n", (long long)(data->waitEnd0.tv_nsec - data->waitStart0.tv_nsec) / 1000);
  51.  
  52.     data->globalWait1 += (long)(data->waitEnd1.tv_nsec - data->waitStart1.tv_nsec) / 1000;
  53.     printf("\tВремя ожидания второго потока %lld мкр. сек. \n", (long long)(data->waitEnd1.tv_nsec - data->waitStart1.tv_nsec) / 1000);
  54.  
  55.     data->globalWait2 += (long)(data->waitEnd2.tv_nsec - data->waitStart2.tv_nsec) / 1000;
  56.     printf("\tВремя ожидания третьего потока %lld мкр. сек. \n", (long long)(data->waitEnd2.tv_nsec - data->waitStart2.tv_nsec) / 1000);
  57.  
  58.     printf("\n\n %s \n\n", denom);
  59. }
  60.  
  61. void reverse(char *str)
  62. {
  63.     char *end = str;
  64.     char buf;
  65.  
  66.     while (*end != '\0')
  67.         end++;
  68.     end--;
  69.  
  70.     while (end > str)
  71.     {
  72.         buf = *str;
  73.         *str = *end;
  74.         *end = buf;
  75.         str++;
  76.         end--;
  77.     }
  78. }
  79.  
  80. void swap(char *str)
  81. {
  82.     char buf;
  83.     char *ptr;
  84.  
  85.     while (*str != '\0')
  86.     {
  87.         buf = *str;
  88.         ptr = str;
  89.         if (*(++ptr) == '\0')
  90.             break;
  91.         *str = *ptr;
  92.         *ptr = buf;
  93.         str += 2;
  94.     }
  95. }
  96.  
  97. void koi8er(char *str)
  98. {
  99.     int len;
  100.     int dig = 0;
  101.     int i = 0;
  102.     char c;
  103.     len = (int)strlen(str);
  104.  
  105.     while ((c = str[i]) != '\0')
  106.     {
  107.         if (c <= (int)'Z' && c >= (int)'A')
  108.         {
  109.             str[i] = c + 32;
  110.             i++;
  111.             continue;
  112.         }
  113.         else if (c <= (int)'z' && c >= (int)'a')
  114.         {
  115.             str[i] = c - 32;
  116.             i++;
  117.             continue;
  118.         }
  119.         else
  120.         {
  121.             str[i] = c;
  122.             i++;
  123.             continue;
  124.         }
  125.     }
  126.  
  127.     for (dig = 0; dig < len; dig++)
  128.     {
  129.         str[dig] += 128;
  130.     }
  131. }
  132.  
  133. void changeCase(int flag, char *strcase)
  134. {
  135.     int len, ch = 0, i = 0;
  136.     char c;
  137.     len = (int)strlen(strcase);
  138.  
  139.     switch (flag % 10)
  140.     {
  141.     case 1:
  142.         for (ch = 0; ch < len; ch++)
  143.         {
  144.             strcase[ch] = toupper(strcase[ch]);
  145.         }
  146.         break;
  147.     case 2:
  148.         for (ch = 0; ch < len; ch++)
  149.         {
  150.             strcase[ch] = tolower(strcase[ch]);
  151.         }
  152.         break;
  153.     case 3:
  154.         while ((c = strcase[i]) != '\0')
  155.         {
  156.             if (c <= (int)'Z' && c >= (int)'A')
  157.             {
  158.                 strcase[i] = c + 32;
  159.                 i++;
  160.                 continue;
  161.             }
  162.             else if (c <= (int)'z' && c >= (int)'a')
  163.             {
  164.                 strcase[i] = c - 32;
  165.                 i++;
  166.                 continue;
  167.             }
  168.             else
  169.             {
  170.                 strcase[i] = c;
  171.                 i++;
  172.                 continue;
  173.             }
  174.         }
  175.     }
  176. }
  177.  
  178. // Функция перехвата сигнала прерывания для ввода команд.
  179. void catchSignal(int sig)
  180. {
  181.     signal(SIGINT, catchSignal);
  182.     char userCommand[10];
  183.     char inputString[] = "\nВведите строку\n";
  184.  
  185.     printf("\n\t----------------------------------------------\n");
  186.     printf("\n\tВыберете тип преобразования сроки процессами\n\n");
  187.  
  188.     printf("%s%s%s%s%s",
  189.            "\tСписок команд для первого процесса :\n\t",
  190.            "/def1 - трансляция строки в неизменном виде;\n\t",
  191.            "/invert - инвертирование строки - первый символ становится последним и т.д.;\n\t",
  192.            "/swap - обмен соседних символов - нечетный становится на место четного и наоборот;\n\t",
  193.            "/koi8 - перевод в кодировку КОИ-8.\n");
  194.  
  195.     printf("%s%s%s%s%s",
  196.            "\n\tСписок команд для второго процесса :\n\t",
  197.            "/def2 - трансляция строки в неизменном виде;\n\t",
  198.            "/upreg - перевод всех символов строки в \"верхний регистр\";\n\t",
  199.            "/lowreg - перевод всех символов строки в \"нижний регистр\";\n\t",
  200.            "/swreg - смена \"регистра\" всех символов строки;\n");
  201.  
  202.     printf("\n\t**************************************\n");
  203.     printf("\n\t/out - завершение программы\n");
  204.     printf("\n\t**************************************\n");
  205.  
  206.     printf("Введите команду:\n");
  207.     scanf("%s", userCommand);
  208.  
  209.     if (strcmp(userCommand, "/continue") == 0)
  210.     {
  211.         flag = flag % 10;
  212.     }
  213.  
  214.     if (strcmp(userCommand, "/def1") == 0)
  215.     {
  216.         flag = flag % 10;
  217.     }
  218.  
  219.     if (strcmp(userCommand, "/invert") == 0)
  220.     {
  221.         flag = flag % 10 + 10;
  222.     }
  223.  
  224.     if (strcmp(userCommand, "/swap") == 0)
  225.     {
  226.         flag = flag % 10 + 20;
  227.     }
  228.  
  229.     if (strcmp(userCommand, "/koi8") == 0)
  230.     {
  231.         flag = flag % 10 + 30;
  232.     }
  233.  
  234.     if (strcmp(userCommand, "/color1") == 0)
  235.     {
  236.         flag = flag % 10 + 50;
  237.     }
  238.  
  239.     if (strcmp(userCommand, "/def2") == 0)
  240.     {
  241.         flag = (flag / 10) * 10;
  242.     }
  243.  
  244.     if (strcmp(userCommand, "/upreg") == 0)
  245.     {
  246.         flag = (flag / 10) * 10 + 1;
  247.     }
  248.  
  249.     if (strcmp(userCommand, "/lowreg") == 0)
  250.     {
  251.         flag = (flag / 10) * 10 + 2;
  252.     }
  253.  
  254.     if (strcmp(userCommand, "/swreg") == 0)
  255.     {
  256.         flag = (flag / 10) * 10 + 3;
  257.     }
  258.  
  259.     if (strcmp(userCommand, "/color2") == 0)
  260.     {
  261.         flag = (flag / 10) * 10 + 5;
  262.     }
  263.  
  264.     if (strcmp(userCommand, "/out") == 0)
  265.     {
  266.         flag = 44;
  267.         printf("\tВыход из программы\n");
  268.     }
  269. }
  270.  
  271. void *process1(void *args)
  272. {
  273.     shared_data *ptr = (shared_data *)args;
  274.     char input[BUF_SIZE];
  275.     struct timespec start1, end1;
  276.     int key = 0;
  277.  
  278.     while (1)
  279.     {
  280.         // чтобы ожидание таймера выполнилось один раз
  281.         if (key != 1)
  282.         {
  283.             clock_gettime(CLOCK_MONOTONIC, &(ptr->waitStart1));
  284.             key = 1;
  285.         }
  286.  
  287.         if ((ptr->done))
  288.         {
  289.             clock_gettime(CLOCK_MONOTONIC, &start1);
  290.  
  291.             printf("\tПоток 1: ");
  292.             strncpy(input, ptr->buf1, strlen(ptr->buf1));
  293.             input[strlen(ptr->buf1) - 1] = '\0';
  294.  
  295.             switch ((int)(flag / 10))
  296.             {
  297.             case 1:
  298.                 reverse(input);
  299.                 break;
  300.             case 2:
  301.                 swap(input);
  302.                 break;
  303.             case 3:
  304.                 koi8er(input);
  305.                 break;
  306.             default:
  307.                 break;
  308.             }
  309.             printf("%s\n", input);
  310.  
  311.             // для передачи управления второму потоку
  312.             strcpy(ptr->buf2, input);
  313.             memset(input, '\0', sizeof(input));
  314.  
  315.             // конец выполнения потока 1
  316.             clock_gettime(CLOCK_MONOTONIC, &end1);
  317.             ptr->globalEx1 += (long)((end1.tv_nsec - start1.tv_nsec) / 1000);
  318.             printf("\t\033[0;32mОчередное время выполнения для потока 1: %lld мкр. сек.\033[0;37m\n", (long long)((end1.tv_nsec - start1.tv_nsec) / 1000));
  319.  
  320.             ptr->done = 0;
  321.             ptr->done1 = 1;
  322.             start1.tv_nsec = end1.tv_nsec = 0;
  323.             // встать в ожидание
  324.             key = 0;
  325.             pthread_barrier_wait(&(ptr->barr[1]));
  326.         }
  327.     }
  328.     pthread_exit(0);
  329. }
  330.  
  331. void *process2(void *args)
  332. {
  333.     shared_data *ptr = (shared_data *)args;
  334.     struct timespec start2, end2;
  335.     char input[BUF_SIZE];
  336.     int key = 0;
  337.     while (1)
  338.     {
  339.         if (key != 1)
  340.         {
  341.             clock_gettime(CLOCK_MONOTONIC, &(ptr->waitStart2));
  342.         }
  343.         key = 1;
  344.         if ((ptr->done1))
  345.         {
  346.             // начало выполнения потока 2
  347.  
  348.             clock_gettime(CLOCK_MONOTONIC, &start2);
  349.             printf("\tПоток 2: ");
  350.             changeCase(flag, ptr->buf2);
  351.             printf("%s\n", ptr->buf2);
  352.             memset(ptr->buf2, '\0', sizeof(ptr->buf2));
  353.             clock_gettime(CLOCK_MONOTONIC, &end2);
  354.             ptr->globalEx2 += (long)((end2.tv_nsec - start2.tv_nsec) / 1000);
  355.             printf("\t\033[0;32mОчередное время выполнения для потока 2: %lld мкр. сек.\033[0;37m\n", (long long)((end2.tv_nsec - start2.tv_nsec) / 1000));
  356.             printf("\n\n");
  357.  
  358.             // конец выполнения потока 2
  359.  
  360.             ptr->done1 = 0;
  361.             key = 0;
  362.             start2.tv_nsec = end2.tv_nsec = 0;
  363.  
  364.             clock_gettime(CLOCK_MONOTONIC, &(ptr->waitEnd0));
  365.  
  366.             clock_gettime(CLOCK_MONOTONIC, &(ptr->waitEnd1));
  367.  
  368.             clock_gettime(CLOCK_MONOTONIC, &(ptr->waitEnd2));
  369.  
  370.             printWaitTimeData(ptr);
  371.  
  372.             ptr->waitEnd0.tv_nsec = ptr->waitStart0.tv_nsec = 0;
  373.             ptr->waitEnd1.tv_nsec = ptr->waitStart1.tv_nsec = 0;
  374.             ptr->waitEnd2.tv_nsec = ptr->waitStart2.tv_nsec = 0;
  375.  
  376.             pthread_barrier_wait(&(ptr->barr[1]));
  377.             pthread_barrier_wait(&(ptr->barr[0]));
  378.         }
  379.     }
  380.     pthread_exit(0);
  381. }
  382.  
  383. int main(int argc, char *argv[])
  384. {
  385.     shared_data data;
  386.     struct timespec start0, end0;
  387.     pthread_t thread[2];
  388.     pthread_attr_t pattr;
  389.     int result;
  390.     data.done = 0;
  391.     data.done1 = 0;
  392.     FILE *ptr;
  393.     char *strResult;
  394.     data.globalEx0 = data.globalEx1 = data.globalEx2 =
  395.         data.globalWait0 = data.globalWait1 = data.globalWait2 = 0;
  396.  
  397.     ptr = fopen("./lab2.txt", "r");
  398.  
  399.     if (ptr == NULL)
  400.     {
  401.         perror("Не удалось открыть файл\n");
  402.         exit(EXIT_FAILURE);
  403.     }
  404.  
  405.     signal(SIGINT, catchSignal);
  406.  
  407.     pthread_attr_init(&pattr);
  408.     pthread_attr_setscope(&pattr, PTHREAD_SCOPE_SYSTEM);
  409.     pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);
  410.  
  411.     for (int i = 0; i < 2; i++)
  412.     {
  413.         if (i == 0)
  414.         {
  415.             if (result = pthread_create(&thread[i], &pattr, process1, &data) != 0)
  416.             {
  417.                 perror("Ошибка создания потока 1\n");
  418.                 exit(EXIT_FAILURE);
  419.             }
  420.             else
  421.             {
  422.                 if (result = pthread_create(&thread[i], &pattr, process2, &data) != 0)
  423.                 {
  424.                     perror("Ошибка создания процесса 2\n");
  425.                     exit(EXIT_FAILURE);
  426.                 }
  427.             }
  428.         }
  429.  
  430.         pthread_barrier_init(&(data.barr[i]), NULL, 2);
  431.     }
  432.  
  433.     printf("\tВведите команды для обработки текста или команду /continue, чтобы продолжить без обработки\n");
  434.  
  435.     // pthread_kill(pthread_self(), SIGINT);
  436.  
  437.     do
  438.     {
  439.         clock_gettime(CLOCK_MONOTONIC, &start0);
  440.  
  441.         if (flag == 44)
  442.         {
  443.             for (int i = 0; i < 2; i++)
  444.             {
  445.                 pthread_kill(thread[i], SIGTERM);
  446.                 break;
  447.             }
  448.         }
  449.  
  450.         strResult = fgets(data.buf1, BUF_SIZE, ptr);
  451.  
  452.         printf("\tПоток 0: ");
  453.         printf("%s", data.buf1);
  454.  
  455.         clock_gettime(CLOCK_MONOTONIC, &end0);
  456.  
  457.         data.globalEx0 += (long)((end0.tv_nsec - start0.tv_nsec) / 1000);
  458.  
  459.         printf("\t\033[0;32mОчередное время выполнения для потока 0: %lld мкр. сек.\033[0;37m\n", (long long)((end0.tv_nsec - start0.tv_nsec) / 1000));
  460.         clock_gettime(CLOCK_MONOTONIC, &(data.waitStart0));
  461.         data.done = 1;
  462.  
  463.         // обнулить счетчки времени
  464.         start0.tv_nsec = end0.tv_nsec = 0;
  465.  
  466.         // ждать дочерние потоки
  467.         pthread_barrier_wait(&(data.barr[0]));
  468.     } while (strResult != NULL);
  469.  
  470.     printTimeData(&data);
  471.  
  472.     pthread_barrier_destroy(&(data.barr[0]));
  473.     pthread_barrier_destroy(&(data.barr[1]));
  474.  
  475.     exit(EXIT_SUCCESS);
  476. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement