Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лаб. 4 ОСиС

.docx
Скачиваний:
0
Добавлен:
29.12.2024
Размер:
1 Mб
Скачать

Лабораторная работа 4

#include <ctype.h>

#include <limits.h>

#include <stdbool.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

#include <sys/time.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <getopt.h>

#include "find_min_max_2.h"

#include "utils_2.h"

pid_t *child_pids;

int pnum = -1;

void alarmFunc(int a){

  for (int i = 0; i < pnum; i++) {

       kill(child_pids[i], SIGKILL);

  }

}

int main(int argc, char **argv) {

  int seed = -1;

  int array_size = -1;

  bool with_files = false;

  int timeout = -1;

  signal(SIGALRM, alarmFunc);

  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},

                                      {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 must be a non-negative number\n");

              return 1;

            }

            break;

          default:

            printf("Index %d is out of options\n", option_index);

        }

        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 = malloc(sizeof(int) * array_size);

  GenerateArray(array, array_size, seed);

  int active_child_processes = 0;

  struct timeval start_time;

  gettimeofday(&start_time, NULL);

  int fd[2];

  if (!with_files) {

    pipe(fd);

  }

  child_pids = malloc(sizeof(pid_t) * pnum);

  for (int i = 0; i < pnum; i++) {

    pid_t child_pid = fork();

    if (child_pid >= 0) {

      active_child_processes += 1;

      child_pids[i] = child_pid;

      if (child_pid == 0) {

        struct MinMax min_max;

        int begin = i * (array_size / pnum);

        int end = (i + 1) * (array_size / pnum);

        if (i == pnum - 1) {

          end = array_size;

        }

        min_max = GetMinMax(array, begin, end);

        if (with_files) {

          char filename[20];

          sprintf(filename, "result_%d.txt", i);

          FILE *file = fopen(filename, "w");

          fprintf(file, "%d %d\n", min_max.min, min_max.max);

          fclose(file);

        } else {

          write(fd[1], &min_max.min, sizeof(min_max.min));

          write(fd[1], &min_max.max, sizeof(min_max.max));

        }

        return 0;

      }

    } else {

      printf("Fork failed!\n");

      return 1;

    }

  }

  if (timeout > 0) {

    // sleep(timeout);

    // for (int i = 0; i < pnum; i++) {

    //   kill(child_pids[i], SIGKILL); // Отправка SIGKILL всем дочерним процессам

      alarm(timeout);

      sleep(timeout);

    }

  while (active_child_processes > 0) {

      wait(NULL);

      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) {

      char filename[20];

      sprintf(filename, "result_%d.txt", i);

      FILE *file = fopen(filename, "r");

      fscanf(file, "%d %d", &min, &max);

      fclose(file);

    } else {

      read(fd[0], &min, sizeof(min));

      read(fd[0], &max, sizeof(max));

    }

    if (min < min_max.min) min_max.min = min;

    if (max > min_max.max) min_max.max = max;

  }

  if (!with_files) {

    close(fd[0]);

    close(fd[1]);

  }

  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;

}

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

int main() {

    pid_t pid;

    // Создание дочернего процесса

    if ((pid = fork()) == 0) {

        // Дочерний процесс

        printf("Дочерний процесс (PID: %d) завершился.\n", getpid());

        exit(0);  // Завершение дочернего процесса

    } else if (pid > 0) {

        // Родительский процесс

        printf("Родительский процесс (PID: %d) спит 10 секунд...\n", getpid());

        sleep(5);  // Ожидание, чтобы дочерний процесс стал зомби

        printf("Родительский процесс завершился.\n");

    } else {

        // Ошибка при создании процесса

        printf("Ошибка fork");

        return 1;

    }

    return 0;

}

Как появляются зомби-процессы: Дочерний процесс завершает свою работу с помощью exit(0). Он становится зомби, так как родительский процесс не вызвал wait().

Чем опасны: Каждый зомби-процесс занимает запись в таблице процессов. Если зомби-процессов становится слишком много, это может привести к исчерпанию ресурсов и невозможности создания новых процессов.

Как избавиться: Родительский процесс должен вызывать wait() или waitpid(), чтобы получить статус завершения дочернего процесса. Это удалит запись о процессе из таблицы процессов.

В process_memory.c выводятся адреса различных переменных и функции в памяти процесса.

etext: Указывает на адрес, где заканчивается сегмент текста (код программы). Это область памяти, где хранится исполняемый код.

edata: Указывает на адрес, где заканчивается сегмент инициализированных данных. Это область памяти, где хранятся глобальные и статические переменные, которые были инициализированы.

end: Указывает на адрес, где заканчивается сегмент неинициализированных данных (bss). Это область памяти, где хранятся глобальные и статические переменные, которые не были инициализированы.

CC=gcc

CFLAGS=-I.

new :  parallel_min_max_2 zombie process_memory

parallel_min_max_2 : parallel_min_max_2.c utils_2.o find_min_max_2.o utils_2.h find_min_max_2.h

    $(CC) -o parallel_min_max_2 utils_2.o find_min_max_2.o parallel_min_max_2.c $(CFLAGS)

zombie : zombie.c

    $(CC) -o zombie -c zombie.c $(CFLAGS)

process_memory : process_memory.c

    $(CC) -o process_memory -c process_memory.c $(CFLAGS)

utils_2.o : utils_2.h

    $(CC) -o utils_2.o -c utils_2.c $(CFLAGS)

find_min_max_2.o : utils_2.h find_min_max_2.h

    $(CC) -o find_min_max_2.o -c find_min_max_2.c $(CFLAGS)

clean :

    rm utils_2.o find_min_max_2.o parallel_min_max_2 zombie process_memory

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#include "utils_2.h"

#include "sum.h"

#include <pthread.h>

#include <getopt.h>

void *ThreadSum(void *args) {

  struct SumArgs *sum_args = (struct SumArgs *)args;

    unsigned long long int *result = malloc(sizeof(unsigned long long int));

    *result = Sum(sum_args);

    return (void *)result;

}

int main(int argc, char **argv) {

 

  uint32_t threads_num = -1;

  uint32_t seed = -1;

  uint32_t array_size = -1;

 

  while (true) {

    int current_optind = optind ? optind : 1;

    static struct option options[] = {

        {"threads_num", required_argument, 0, 0},

        {"seed", required_argument, 0, 0},

        {"array_size", 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:

                      threads_num = atoi(optarg);

                      if (threads_num <= 0) {

                          printf("threads_num must be a positive number\n");

                          return 1;

                      }

                      break;

                  case 1:

                      seed = atoi(optarg);

                      if (seed <= 0) {

                          printf("seed must be a positive number\n");

                          return 1;

                      }

                      break;

                  case 2:

                      array_size = atoi(optarg);

                      if (array_size <= 0) {

                          printf("array_size must be a positive number\n");

                          return 1;

                      }

                      break;

                  default:

                      printf("Index %d is out of options\n", option_index);

              }

              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 || threads_num == -1) {

    printf("Usage: %s --seed \"num\" --array_size \"num\" --pnum \"num\" --timeout \"num\"\n",

           argv[0]);

    return 1;

  }

  pthread_t threads[threads_num];

  int *array = malloc(sizeof(int) * array_size);

  GenerateArray(array, array_size, seed);

  struct SumArgs args[threads_num];

  int chunk_size = array_size / threads_num;

   clock_t start_time = clock();

  for (uint32_t i = 0; i < threads_num; i++) {

    args[i].array = array;

    args[i].begin = i * chunk_size;

    args[i].end = (i + 1) * chunk_size;

    if (i == threads_num - 1) {

        args[i].end = array_size;

    }

    if (pthread_create(&threads[i], NULL, ThreadSum, (void *)&args[i])) {

        printf("Error: pthread_create failed!\n");

        return 1;

    }

  }

  unsigned long long int total_sum = 0;

  for (uint32_t i = 0; i < threads_num; i++) {

      unsigned long long int *sum;

      pthread_join(threads[i], (void **)&sum);

      total_sum += *sum;

      //free(sum);

  }

  clock_t end_time = clock();

  double time_taken = (double)(end_time - start_time) / CLOCKS_PER_SEC;

  free(array);

  printf("Total: %llu\n", total_sum);

  printf("Time taken to calculate sum: %.6f seconds\n", time_taken);

  return 0;

}

CC = gcc

CFLAGS = -I.

new: parallel_min_max_2 zombie process_memory psum

parallel_min_max_2: parallel_min_max_2.c utils_2.o find_min_max_2.o utils_2.h find_min_max_2.h

    $(CC) -o parallel_min_max_2 utils_2.o find_min_max_2.o parallel_min_max_2.c $(CFLAGS)

zombie: zombie.c

    $(CC) -o zombie zombie.c $(CFLAGS)

process_memory: process_memory.c

    $(CC) -o process_memory process_memory.c $(CFLAGS)

psum: parallel_sum.o sum.o utils_2.o sum.h utils_2.h

    $(CC) -o psum parallel_sum.o sum.o utils_2.o -lpthread $(CFLAGS)

utils_2.o: utils_2.c utils_2.h

    $(CC) -c utils_2.c $(CFLAGS)

find_min_max_2.o: find_min_max_2.c find_min_max_2.h utils_2.h

    $(CC) -c find_min_max_2.c $(CFLAGS)

sum.o: sum.c sum.h

    $(CC) -c sum.c $(CFLAGS)

parallel_sum.o: parallel_sum.c sum.h utils_2.h

    $(CC) -c parallel_sum.c $(CFLAGS)

clean:

    rm -f utils_2.o find_min_max_2.o parallel_min_max_2 zombie process_memory parallel_sum.o sum.o psum

Соседние файлы в предмете Операционные системы и сети