Порядок, в котором будут выполняться процессы

Я новичок в C, поэтому прошу прощения, если это простой вопрос. Я пишу программу на C, часть которой приведена ниже. Целью всей программы является копирование файла из одного места в другое (файлы передаются в качестве аргументов, а последний аргумент является местом назначения). main(), приведенный ниже, использует fork() для создания одного дочернего процесса для каждого переданного файла, и мне нужно распечатать имя файла (только входной аргумент) вместе с сообщением, которое может включать PID для каждой попытки копирования после запуска всех дочерних процессов. .

Очевидно, что я могу получить и использовать PID, это не проблема, но как я могу получить правильное имя файла/аргумент, связанный с этим процессом? Метод, который у меня сейчас есть, явно неверен; простое повторение каждого аргумента по порядку будет неправильным. Это будет работать на Minix 2.0.4, но я не знаю, имеет ли это значение.

int
main(int argc, char *argv[])
{
   int i, pid, rem, status;
   int pids[argc];
   char cfstatus[];

   rem = argc;

   for(i = 1; i < argc; i++) {
      if((pids[i] = fork()) < 0) {
         fprintf(stderr, "Error while forking");
      }
      else if(pids[i] == 0) {
         if(copyfile(argv[i], argv[argc - 1]) == 1)
            exit(4);
         else
            exit(0);
      }
   }

   i = 0;

   while(rem > 1) {
      pid = wait(&status);
      cfstatus = getcfstatus(status, pid);
      printf("%-20s: %s", argv[i], cfstatus);
      rem--;
      i++;
   }
}

person vaindil    schedule 16.02.2015    source источник
comment
код должен проверить, что argc равен (по крайней мере) 3, и если этот тест не пройден, вывести сообщение об ошибке, указывающее правильный формат, а затем выйти   -  person user3629249    schedule 16.02.2015
comment
argc включает счетчик для имени программы (это имя находится в argv[0])), поэтому код необходимо изменить, чтобы учесть эти две детали.   -  person user3629249    schedule 16.02.2015
comment
Ах хорошо. Он проверяет количество аргументов и терпит неудачу, если передано слишком мало, но я удалил эту проверку, чтобы сохранить фрагмент кода по существу.   -  person vaindil    schedule 16.02.2015


Ответы (2)


Как сейчас написано, дочерний процесс, чей PID хранится в pids[i], будет работать с файлом, названным argv[i]. В этом нет никакой неопределенности. i дублируется вместе со всем остальным операцией fork и после этого не изменяется.

Однако, поскольку все дочерние элементы выполняются параллельно, они могут завершаться в любом порядке. То есть каждый вызов wait может возвращать любой из PID в массиве (который еще не был возвращен). Итак, что вам нужно сделать в вашем цикле wait, это сопоставить назад от значения pid, возвращаемого wait, к его индексу в массиве pids, и тогда вы знаете правильный индекс в argv для печати. Для такой программы, вероятно, будет достаточно линейного поиска в массиве.

person zwol    schedule 16.02.2015
comment
Это имеет смысл. Спасибо, я очень ценю это! - person vaindil; 16.02.2015

эта строка (кроме «i» не должна быть 0) имеет несколько проблем

"if(copyfile(argv[i], argv[argc - 1]) == 1)'

если командная строка: имя программы srcFile desFile

тогда argc = 3 затем argv[argc-1] = srcFile, что не то, что нужно

предложить:

'if(copyfile(argv[i], argv[argc]) == 1)'

затем, чтобы избежать состояния гонки при записи в output/desFile

только один процесс может писать в этот файл в любой момент времени.

поэтому разветвление нескольких процессов для записи в один и тот же файл является ошибкой

эта строка:

'for(i = 0; i < argc; i++) {'

требуется несколько модификаций, чтобы (среди прочего) избежать попыток скопировать исполняемый файл в desFile и избежать попыток скопировать desFile в себя

предложить:

'for(i = 1; i < (argc-1); i++) {'
person user3629249    schedule 16.02.2015
comment
argv[] имеет индекс 0, поэтому, используя ваш пример argc = 3 и, следовательно, argv[argc - 1] = argv[2] = desFile. Остальное имеет смысл. Благодарю вас! - person vaindil; 16.02.2015