waitpid не дает мне последовательных результатов - PullRequest
1 голос
/ 25 февраля 2020

Edit: я должен сначала уточнить, когда waitpid не работает, он не работает для всех процессов. Как и предполагалось, я распечатал возвращаемое значение waitpid и получил интересные результаты. Во-первых, во время неудачных запусков waitpid () возвращает 0, даже когда WIFEXITED (статистика) возвращает 1. Как мог дочерний процесс не иметь никаких изменений в статусе, но возвращение завершено?

Во-вторых, я использовал фиктивную программу, которая печатает выходить строковый аргумент каждую 1 секунду в течение указанного количества раз. (Вот как я отследил, если программа завершена). Я заметил, что во время успешных запусков значение waitpid не распечатывалось во время переключения контекста, но после завершения всех процессов.

примерно так: (здесь предполагается, что каждая прога требует 2 квоты для завершения) "прога prog1" "prog2 run" "prog3 run" "prog1 run" "prog2 run" "prog3 run" waitpid: 0 waitpid: 0 waitpid: 0 ...

с другой стороны, неудачный запуск дал мне следующее: «prog1 run» waitpid: 0 обнаружение завершения программы «prog2 run» waitpid: 0 обнаружение завершения программы «prog3 run» waitpid: 0 обнаружение завершения программы

TLDR: возможно ли значение waitpid (child_PID, stat, WNOHANG) чтобы дать другой WIFEXITED (stat) в разных программах одной и той же программы?

Я кодирую планировщик циклического перебора. Родительский процесс разветвляется на n дочерних процессов, каждый из которых запускает процесс в планировщике. Используя сигналы SIGCONT и SIGSTOP, а также функцию usleep (), родитель может выделить определенные временные квоты для каждого из дочерних процессов для последовательного запуска в цикле. В конце каждой квоты родитель проверяет, завершен ли какой-либо процесс. Для этого используется waitpid (child_PID, stat, WNOHANG); а затем WIFEXITED (стат). Если процесс завершен, родитель не будет выделять больше временных квот для этого процесса в последующих циклах.

Тем не менее, я заметил, что в любой другой раз, когда я запускаю код, WIFEXITED (stat) дает мне 1 даже после первого цикла квот я даже подумал, что каждый процесс должен выполняться намного дольше, чем указанная квота. Я точно знаю, что программы не должны были быть завершены, потому что мои тестовые программы предполагают печать определенного числа строк перед выходом. Самое странное, что WIFEXITED дает мне неправильные результаты точно при каждом ДРУГОМ прогоне, и в первом цикле.

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

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <stdbool.h>

int main(int argc, char *argv[]) {
  int tick_interval = 10000;
  char opt;
  while ((opt = getopt(argc, argv, "t:")) != -1) {
    switch (opt) {
    case 't':
      tick_interval = atoi(optarg);
      break;
    default:
      goto usage;
    }
  }

  if (optind >= argc) {
    goto usage;
  }

  char *filepath = argv[optind];//filepath to textfile containing name of programs and arguments.
  int n;
  FILE * fp;
  char * line = NULL;
  size_t len = 0;
  ssize_t read;

  printf("parent PID: %d\n", getpid());
  fp = fopen(filepath, "r");
  if (fp == NULL)
      exit(EXIT_FAILURE);
  int PID;
  int *prog_tracker = malloc(0);
  int line_counter = 0;
  int word_counter;
  int word_length;
  char ***lines = malloc(0);
  while ((read = getline(&line, &len, fp)) != -1) {
      //printf("round %d\n", line_counter);
      word_counter = 0;
      word_length = 0;
      lines = realloc(lines, (++line_counter) * sizeof(char**));
      lines[line_counter - 1] = malloc(0);
      int char_counter;
      bool is_new = 1;
      for (char_counter = 0; char_counter < read; char_counter ++) {
          if (is_new) {
              is_new = 0;
              lines[line_counter - 1] = realloc(lines[line_counter - 1], ++word_counter * sizeof(char*));
              lines[line_counter - 1][word_counter - 1] = malloc(0);
          }
          lines[line_counter - 1][word_counter - 1] = realloc(lines[line_counter - 1][word_counter - 1], ++word_length * sizeof(char));
          if (line[char_counter] == ' '||line[char_counter] == '\0' || line[char_counter] == '\n' || line[char_counter] == EOF) {
              is_new = 1;
              lines[line_counter - 1][word_counter - 1][word_length - 1] = '\0';
              word_length = 0;
          } else {
              lines[line_counter - 1][word_counter - 1][word_length - 1] = line[char_counter];
          }
      }
      //first line states number of cores to be used. To be implemented. Ignored for now.
      if (line_counter != 1) {
          PID = fork();
          if (PID != 0) {
              printf("PID: %d created at: %d\n", PID, line_counter);
              kill(PID, SIGSTOP);
              prog_tracker = realloc(prog_tracker, (line_counter - 1)  * sizeof(int));
              prog_tracker[line_counter - 2] = PID;
          } else {
              char *arguments[word_counter + 1];
              int counter;
              for (counter = 0; counter < word_counter; counter ++) {
                  arguments[counter] = lines[line_counter - 1][counter];
              }
              arguments[word_counter] = NULL;
              execv(arguments[0], arguments);//child processes implement processes in file.
              break;
          }
      }
  }
  free(lines);
  fclose(fp);
  if (line)
      free(line);

  if (PID != 0) {
      printf("parent running %d\n", getpid());
      int proc_num = 0;
      int prog_num = line_counter - 1;
      printf("prog_num: %d\n", prog_num);
      while (prog_num != 0) { //The while loop should break when all programs have finished, but it does not.
          kill(prog_tracker[proc_num], SIGCONT);
          usleep(tick_interval * 1000);
          kill(prog_tracker[proc_num], SIGSTOP);
          int stat;
           printf("status: %d", waitpid(prog_tracker[proc_num], &stat, WNOHANG)); //I now print out the return of waitpid.
          printf("%d\n", WIFEXITED(stat));
          if (WIFEXITED(stat)) {
              //printf("%d\n", WIFEXITED(stat));
              printf("program termination detected\n");
              prog_tracker[proc_num] = 0;
              prog_num -= 1;
              printf("processes left %d\n", prog_num);
          }
          proc_num = (++proc_num) % (line_counter - 1);
          while(prog_tracker[proc_num] == 0) {
              proc_num = (++proc_num) % (line_counter - 1);
          }
       }
       printf("All programs ended.");//This never gets printed!
  }
  return 0;

1 Ответ

2 голосов
/ 26 февраля 2020

код такого типа:

        PID = fork();
        if (PID != 0) 
        {   << then running parent process or error occurred
            printf("PID: %d created at: %d\n", PID, line_counter);
            kill(PID, SIGSTOP);
            prog_tracker = realloc(prog_tracker, (line_counter - 1)  * sizeof(int));
            prog_tracker[line_counter - 2] = PID;
        }

, если вызов fork() был успешным, это убивает дочерний процесс. Наверное, не то, что вы хотите.

...