Как я могу отправить аргументы командной строки в массив malloc, а затем отправить эти аргументы из родительского процесса в дочерний процесс - PullRequest
1 голос
/ 31 мая 2019

Это для школьного задания, и я знаю, что это о простой проблеме, как есть, но из-за своей жизни я не могу понять, что я делаю неправильно.

В родителепроцесс, мне нужно преобразовать аргументы cmdline в целые числа, а затем сохранить аргументы в массиве malloc.Затем мне нужно отправить каждое целое число дочернему процессу по одному.Затем дочерний процесс суммирует все целые числа, переданные из родительского процесса.Как только суммирование завершено, оно вернет сумму в родительский процесс.Затем родительский процесс выводит сумму.

Есть три вещи, которые я не понимаю в этом коде.

  1. Получение аргументов командной строки, преобразование их в целые числа и сохранение их с использованиемуказатель на массив malloc.Я не понимаю, почему я не могу просто написать это в моем родительском процессе:
  int* numArray = (int*) malloc (argc * sizeof(int));
  for(int i = 0; i < argc; ++i){
     numArray[i] = atoi(argv[i+1]);
  }

Как я могу отправить отдельные значения дочернему процессу для суммирования?Я могу читать их по одному, а затем увеличивать сумму на значение в sumBuf.Затем sumBuf перезаписывается следующим значением и снова увеличивает сумму на sumBuf.Как я могу это сделать?

Как получить доступ к возвращаемому дочернему значению в родительском процессе?

Хранение целых чисел в malloc массив дает ошибку сегментации, и я не понимаю, как это исправить.Кроме того, поскольку fork возвращает PID дочернего элемента, если дочерний элемент возвращает сумму, не должна ли сумма быть PID дочернего элемента?

  1. Для массива malloc, который я пытался разыменовать numArrayвнутри цикла for, как:
   *numArray[i] = atoi(argv[i+1]) 

Я пытался записать отдельные значения в канал внутри цикла for

Я знаю, что fork возвращает дочернее значение PID, поэтому, если child возвращает сумму, не следуетsum = p, сохранить сумму в значение суммы родителя?

int main(int argc, char **argv){
  int *numArray = (int*) malloc (argc * sizeof(int));
  pid_t p;
  int fd[2];
  pipe(fd);
  p = fork()
  //error checks

  if(p == 0){//child process
       int sum = 0;
       int sumBuf = 0;
       close(fd[1]);//close write end
       for(int i = 0; i < argc; ++i){
           read(fd[0], sumBuf, sizeof(int));
           sum += sumBuf;
       }
       close(fd[0]);//close read end
       return sum;//return sum from child process
   }
   else{//parent process
       int sum = 0;
       close(fd[0]);//close read end
       for(int i = 0; i < argc; ++i){
           numArray[i] = atoi(argv[i+1]);
           write(fd[1], numArray[i], sizeof(int));
       }
       close(fd[1]);//close write end of pipe
       sum = p;
       printf("Sum = %d", sum);
       return 0;
   }
   free(numArray);
   return 0;
}

При попытке запустить эту программу я получаю сообщение об ошибке сегментации.Пожалуйста, не называй меня глупым, я понимаю идею того, что делать, но я не понимаю, как это реализовать ..

Ответы [ 2 ]

2 голосов
/ 31 мая 2019

Прежде чем перейти к главному ... Я предполагаю, что вы положили туда #include <stdlib.h> (а также <stdio.h> и <unistd.h>).

Это:

int *numArray = (int*) malloc (argc * sizeof(int));

банкабыть заменено на лучшую альтернативу:

int *numArray = malloc(argc * sizeof *numArray);

Приведение не требуется.Кроме того, лучше использовать sizeof *pointer, так как если вам нужно изменить тип данных, указанный массивом, вам не нужно менять sizeof.Кроме того, если вы забудете #include <stdlib.h>, malloc() вернет int.Помещение приведения в основном говорит компилятору об этом молчать.Если вы не поставите приведение, вы получите диагностическое сообщение.

По хорошей привычке также лучше проверить возвращаемое значение malloc(), например,

if (!numArray) {
    return EXIT_FAILURE;
}

Кроме того, strtol() лучше, чем atoi(), так как первый обеспечивает проверку ошибок.

Nitpick: вам нужно поставить ; после fork().

Если вам нужночтобы вернуть значение от ребенка к родителю, вы не можете делать то, что сделали: sum = p;.Вместо этого вам следует создать другой канал, если операционная система не поддерживает двунаправленные каналы (вероятно, безопаснее это предположить).Я оставляю это как упражнение для вас.

Теперь write() и read() нужен их второй аргумент - указатель.Так, например, read() должно быть:

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

Аналогично для write().

Я не понимаю, что вы имеете в виду, почему вы не можете просто написатьmalloc() в родительском процессе.Вы, конечно, можете, и это лучше, так как дочерний процесс, как я понимаю, не должен иметь доступа к выделенной памяти.

Теперь наиболее вероятной причиной segfault является неопределенное поведение, вызванное чтением за пределами привязанного массива.В этом случае argv.Это, вероятно, проще объяснить, используя пример:

Если вы запустите его таким образом:

./a.out 1 2 3

argc будет равно 4, то есть вы можете получить доступ только к argv[0] to argv[3].Теперь вот подсказка: посмотрите на петли.

0 голосов
/ 31 мая 2019
  1. Я не понимаю, почему я не могу просто написать это в моем родительском процессе - это именно то, что вы сделали, и это должно работать.В этом нет ничего плохого.

  2. Функции read и write принимают адрес буфера в качестве второго аргумента.Вы пытались передать значение переменных.Измените следующие строки как -

read(fd[0], sumBuf, sizeof(int));

на

read(fd[0], &sumBuf, sizeof(int));

и

write(fd[1], numArray[i], sizeof(int));

на

write(fd[1], &(numArray[i]), sizeof(int));

Это должно решить проблему для вас.Кроме того, ваш компилятор должен предупредить вас об этом.Пожалуйста, рассматривайте все предупреждения как ошибки.

Вы можете получить доступ к идентификатору дочернего процесса в родительском элементе, посмотрев на возвращаемое значение fork.В вашем случае переменная p.

Похоже, у вас также есть путаница между PID и значением, которое возвращает процесс.PID - это идентификатор процесса.Это уникально для процесса.Возвращаемое значение - это то, что возвращает основная функция этого процесса.Это может быть целое число (два процесса также могут возвращать одно и то же значение).Родитель может получить доступ к значению, которое возвращает его потомок, используя функцию wait.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...