Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/wait.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <signal.h>
- #include <ctype.h>
- #include <pthread.h>
- #include <time.h>
- #define BUF_SIZE 256
- void reverse(char *);
- void changeCase(int, char *);
- void koi8er(char *);
- void swap(char *);
- void catchSignal(int);
- void commandToLowerCase(char *);
- int flag;
- struct SHARED_DATA
- {
- pthread_barrier_t barr[2];
- char buf1[BUF_SIZE], buf2[BUF_SIZE];
- int done, done1;
- struct timespec waitStart0, waitEnd0,
- waitStart1, waitEnd1, waitStart2, waitEnd2;
- long globalEx0, globalEx1, globalEx2;
- long globalWait0, globalWait1, globalWait2;
- };
- typedef struct SHARED_DATA shared_data;
- void printTimeData(shared_data *data)
- {
- printf("\tОбщее время обработки текста первым потоком: %lld мкр. сек.\n", (long long)(data->globalEx0));
- printf("\tОбщее время обработки текста вторым потоком: %lld мкр. сек.\n", (long long)(data->globalEx1));
- printf("\tОбщее время обработки текста третьим потоком: %lld мкр. сек.\n", (long long)(data->globalEx2));
- printf("\tОбщее время ожидания первого потока: %lld мкр. сек.\n", (long long)(data->globalWait0));
- printf("\tОбщее время ожидания второго потока: %lld мкр. сек.\n", (long long)(data->globalWait1));
- printf("\tОбщее время ожидания третього потока: %lld мкр. сек.\n", (long long)(data->globalWait2));
- }
- void printWaitTimeData(shared_data *data)
- {
- char denom[BUF_SIZE / 2];
- memset(denom, '-', BUF_SIZE / 2);
- data->globalWait0 += (long)(data->waitEnd0.tv_nsec - data->waitStart0.tv_nsec) / 1000;
- printf("\tВремя ожидания первого потока %lld мкр. сек. \n", (long long)(data->waitEnd0.tv_nsec - data->waitStart0.tv_nsec) / 1000);
- data->globalWait1 += (long)(data->waitEnd1.tv_nsec - data->waitStart1.tv_nsec) / 1000;
- printf("\tВремя ожидания второго потока %lld мкр. сек. \n", (long long)(data->waitEnd1.tv_nsec - data->waitStart1.tv_nsec) / 1000);
- data->globalWait2 += (long)(data->waitEnd2.tv_nsec - data->waitStart2.tv_nsec) / 1000;
- printf("\tВремя ожидания третьего потока %lld мкр. сек. \n", (long long)(data->waitEnd2.tv_nsec - data->waitStart2.tv_nsec) / 1000);
- printf("\n\n %s \n\n", denom);
- }
- void reverse(char *str)
- {
- char *end = str;
- char buf;
- while (*end != '\0')
- end++;
- end--;
- while (end > str)
- {
- buf = *str;
- *str = *end;
- *end = buf;
- str++;
- end--;
- }
- }
- void swap(char *str)
- {
- char buf;
- char *ptr;
- while (*str != '\0')
- {
- buf = *str;
- ptr = str;
- if (*(++ptr) == '\0')
- break;
- *str = *ptr;
- *ptr = buf;
- str += 2;
- }
- }
- void koi8er(char *str)
- {
- int len;
- int dig = 0;
- int i = 0;
- char c;
- len = (int)strlen(str);
- while ((c = str[i]) != '\0')
- {
- if (c <= (int)'Z' && c >= (int)'A')
- {
- str[i] = c + 32;
- i++;
- continue;
- }
- else if (c <= (int)'z' && c >= (int)'a')
- {
- str[i] = c - 32;
- i++;
- continue;
- }
- else
- {
- str[i] = c;
- i++;
- continue;
- }
- }
- for (dig = 0; dig < len; dig++)
- {
- str[dig] += 128;
- }
- }
- void changeCase(int flag, char *strcase)
- {
- int len, ch = 0, i = 0;
- char c;
- len = (int)strlen(strcase);
- switch (flag % 10)
- {
- case 1:
- for (ch = 0; ch < len; ch++)
- {
- strcase[ch] = toupper(strcase[ch]);
- }
- break;
- case 2:
- for (ch = 0; ch < len; ch++)
- {
- strcase[ch] = tolower(strcase[ch]);
- }
- break;
- case 3:
- while ((c = strcase[i]) != '\0')
- {
- if (c <= (int)'Z' && c >= (int)'A')
- {
- strcase[i] = c + 32;
- i++;
- continue;
- }
- else if (c <= (int)'z' && c >= (int)'a')
- {
- strcase[i] = c - 32;
- i++;
- continue;
- }
- else
- {
- strcase[i] = c;
- i++;
- continue;
- }
- }
- }
- }
- // Функция перехвата сигнала прерывания для ввода команд.
- void catchSignal(int sig)
- {
- signal(SIGINT, catchSignal);
- char userCommand[10];
- char inputString[] = "\nВведите строку\n";
- printf("\n\t----------------------------------------------\n");
- printf("\n\tВыберете тип преобразования сроки процессами\n\n");
- printf("%s%s%s%s%s",
- "\tСписок команд для первого процесса :\n\t",
- "/def1 - трансляция строки в неизменном виде;\n\t",
- "/invert - инвертирование строки - первый символ становится последним и т.д.;\n\t",
- "/swap - обмен соседних символов - нечетный становится на место четного и наоборот;\n\t",
- "/koi8 - перевод в кодировку КОИ-8.\n");
- printf("%s%s%s%s%s",
- "\n\tСписок команд для второго процесса :\n\t",
- "/def2 - трансляция строки в неизменном виде;\n\t",
- "/upreg - перевод всех символов строки в \"верхний регистр\";\n\t",
- "/lowreg - перевод всех символов строки в \"нижний регистр\";\n\t",
- "/swreg - смена \"регистра\" всех символов строки;\n");
- printf("\n\t**************************************\n");
- printf("\n\t/out - завершение программы\n");
- printf("\n\t**************************************\n");
- printf("Введите команду:\n");
- scanf("%s", userCommand);
- if (strcmp(userCommand, "/continue") == 0)
- {
- flag = flag % 10;
- }
- if (strcmp(userCommand, "/def1") == 0)
- {
- flag = flag % 10;
- }
- if (strcmp(userCommand, "/invert") == 0)
- {
- flag = flag % 10 + 10;
- }
- if (strcmp(userCommand, "/swap") == 0)
- {
- flag = flag % 10 + 20;
- }
- if (strcmp(userCommand, "/koi8") == 0)
- {
- flag = flag % 10 + 30;
- }
- if (strcmp(userCommand, "/color1") == 0)
- {
- flag = flag % 10 + 50;
- }
- if (strcmp(userCommand, "/def2") == 0)
- {
- flag = (flag / 10) * 10;
- }
- if (strcmp(userCommand, "/upreg") == 0)
- {
- flag = (flag / 10) * 10 + 1;
- }
- if (strcmp(userCommand, "/lowreg") == 0)
- {
- flag = (flag / 10) * 10 + 2;
- }
- if (strcmp(userCommand, "/swreg") == 0)
- {
- flag = (flag / 10) * 10 + 3;
- }
- if (strcmp(userCommand, "/color2") == 0)
- {
- flag = (flag / 10) * 10 + 5;
- }
- if (strcmp(userCommand, "/out") == 0)
- {
- flag = 44;
- printf("\tВыход из программы\n");
- }
- }
- void *process1(void *args)
- {
- shared_data *ptr = (shared_data *)args;
- char input[BUF_SIZE];
- struct timespec start1, end1;
- int key = 0;
- while (1)
- {
- // чтобы ожидание таймера выполнилось один раз
- if (key != 1)
- {
- clock_gettime(CLOCK_MONOTONIC, &(ptr->waitStart1));
- key = 1;
- }
- if ((ptr->done))
- {
- clock_gettime(CLOCK_MONOTONIC, &start1);
- printf("\tПоток 1: ");
- strncpy(input, ptr->buf1, strlen(ptr->buf1));
- input[strlen(ptr->buf1) - 1] = '\0';
- switch ((int)(flag / 10))
- {
- case 1:
- reverse(input);
- break;
- case 2:
- swap(input);
- break;
- case 3:
- koi8er(input);
- break;
- default:
- break;
- }
- printf("%s\n", input);
- // для передачи управления второму потоку
- strcpy(ptr->buf2, input);
- memset(input, '\0', sizeof(input));
- // конец выполнения потока 1
- clock_gettime(CLOCK_MONOTONIC, &end1);
- ptr->globalEx1 += (long)((end1.tv_nsec - start1.tv_nsec) / 1000);
- printf("\t\033[0;32mОчередное время выполнения для потока 1: %lld мкр. сек.\033[0;37m\n", (long long)((end1.tv_nsec - start1.tv_nsec) / 1000));
- ptr->done = 0;
- ptr->done1 = 1;
- start1.tv_nsec = end1.tv_nsec = 0;
- // встать в ожидание
- key = 0;
- pthread_barrier_wait(&(ptr->barr[1]));
- }
- }
- pthread_exit(0);
- }
- void *process2(void *args)
- {
- shared_data *ptr = (shared_data *)args;
- struct timespec start2, end2;
- char input[BUF_SIZE];
- int key = 0;
- while (1)
- {
- if (key != 1)
- {
- clock_gettime(CLOCK_MONOTONIC, &(ptr->waitStart2));
- }
- key = 1;
- if ((ptr->done1))
- {
- // начало выполнения потока 2
- clock_gettime(CLOCK_MONOTONIC, &start2);
- printf("\tПоток 2: ");
- changeCase(flag, ptr->buf2);
- printf("%s\n", ptr->buf2);
- memset(ptr->buf2, '\0', sizeof(ptr->buf2));
- clock_gettime(CLOCK_MONOTONIC, &end2);
- ptr->globalEx2 += (long)((end2.tv_nsec - start2.tv_nsec) / 1000);
- printf("\t\033[0;32mОчередное время выполнения для потока 2: %lld мкр. сек.\033[0;37m\n", (long long)((end2.tv_nsec - start2.tv_nsec) / 1000));
- printf("\n\n");
- // конец выполнения потока 2
- ptr->done1 = 0;
- key = 0;
- start2.tv_nsec = end2.tv_nsec = 0;
- clock_gettime(CLOCK_MONOTONIC, &(ptr->waitEnd0));
- clock_gettime(CLOCK_MONOTONIC, &(ptr->waitEnd1));
- clock_gettime(CLOCK_MONOTONIC, &(ptr->waitEnd2));
- printWaitTimeData(ptr);
- ptr->waitEnd0.tv_nsec = ptr->waitStart0.tv_nsec = 0;
- ptr->waitEnd1.tv_nsec = ptr->waitStart1.tv_nsec = 0;
- ptr->waitEnd2.tv_nsec = ptr->waitStart2.tv_nsec = 0;
- pthread_barrier_wait(&(ptr->barr[1]));
- pthread_barrier_wait(&(ptr->barr[0]));
- }
- }
- pthread_exit(0);
- }
- int main(int argc, char *argv[])
- {
- shared_data data;
- struct timespec start0, end0;
- pthread_t thread[2];
- pthread_attr_t pattr;
- int result;
- data.done = 0;
- data.done1 = 0;
- FILE *ptr;
- char *strResult;
- data.globalEx0 = data.globalEx1 = data.globalEx2 =
- data.globalWait0 = data.globalWait1 = data.globalWait2 = 0;
- ptr = fopen("./lab2.txt", "r");
- if (ptr == NULL)
- {
- perror("Не удалось открыть файл\n");
- exit(EXIT_FAILURE);
- }
- signal(SIGINT, catchSignal);
- pthread_attr_init(&pattr);
- pthread_attr_setscope(&pattr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);
- for (int i = 0; i < 2; i++)
- {
- if (i == 0)
- {
- if (result = pthread_create(&thread[i], &pattr, process1, &data) != 0)
- {
- perror("Ошибка создания потока 1\n");
- exit(EXIT_FAILURE);
- }
- else
- {
- if (result = pthread_create(&thread[i], &pattr, process2, &data) != 0)
- {
- perror("Ошибка создания процесса 2\n");
- exit(EXIT_FAILURE);
- }
- }
- }
- pthread_barrier_init(&(data.barr[i]), NULL, 2);
- }
- printf("\tВведите команды для обработки текста или команду /continue, чтобы продолжить без обработки\n");
- // pthread_kill(pthread_self(), SIGINT);
- do
- {
- clock_gettime(CLOCK_MONOTONIC, &start0);
- if (flag == 44)
- {
- for (int i = 0; i < 2; i++)
- {
- pthread_kill(thread[i], SIGTERM);
- break;
- }
- }
- strResult = fgets(data.buf1, BUF_SIZE, ptr);
- printf("\tПоток 0: ");
- printf("%s", data.buf1);
- clock_gettime(CLOCK_MONOTONIC, &end0);
- data.globalEx0 += (long)((end0.tv_nsec - start0.tv_nsec) / 1000);
- printf("\t\033[0;32mОчередное время выполнения для потока 0: %lld мкр. сек.\033[0;37m\n", (long long)((end0.tv_nsec - start0.tv_nsec) / 1000));
- clock_gettime(CLOCK_MONOTONIC, &(data.waitStart0));
- data.done = 1;
- // обнулить счетчки времени
- start0.tv_nsec = end0.tv_nsec = 0;
- // ждать дочерние потоки
- pthread_barrier_wait(&(data.barr[0]));
- } while (strResult != NULL);
- printTimeData(&data);
- pthread_barrier_destroy(&(data.barr[0]));
- pthread_barrier_destroy(&(data.barr[1]));
- exit(EXIT_SUCCESS);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement