2016-03-12 3 views
0

Я пытаюсь использовать pipe() от родителя к детям, чтобы суммировать части файла. Дети получают позицию в файле, суммируют свои обозначенные номера, отправляют свою сумму обратно, а родитель суммирует дочерние суммы.Select() никогда не возвращает true

У меня возникли проблемы с кодом в родительском разделе, чтобы прочитать его, когда это будет сделано.

Код:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/types.h> 
#include <sys/select.h> 
#include <time.h> 

int main(int argc, char *argv[]) 
{ 
int numchild; 
struct timeval stop, start; 
int i, j, len, ret, fpos=0, val, count=0, total=0, alltotal=0; 
pid_t pid; 
int nums = 1000; 
FILE * file; 

printf("How many children to use: "); 
scanf("%d", &numchild); 
printf("\nWill use %d child process(es).\n", numchild); 

gettimeofday(&start, NULL); 
int fd[numchild][2]; //parent to child. one for each 
int results[2]; //all children to parent 
pipe(results); 

fd_set result_fd; 
FD_ZERO(&result_fd); 
FD_SET(results[0], &result_fd); 
struct timeval tm = {.tv_sec=0, .tv_usec=1}; 

// create all pipes 
for (i=0; i<numchild; i++) 
{ 
    pipe(fd[i]); 
} 

for (i=0; i<numchild; i++) 
{ 
    if((pid = fork()) == 0) // child process 
    { 
     pid = getpid(); 

     // read from parent 
     len = read(fd[i][0], &fpos, sizeof(fpos)); 
     if (len > 0) 
     { 
      file = fopen("file1.dat", "r"); 
      fseek (file, fpos, SEEK_SET); 
      count = 0; 
      total = 0; 

      printf("Child(%d): Recieved position: %d\n", pid, fpos); 

      // read from file starting at fpos 
      // add values read to a total value 
      while (count < (nums/numchild)) 
      { 
       fscanf(file, "%i", &val); 
       total += val; 
       count++; 
      } 
      //write to parent 
      write(results[1], &total, sizeof(total)); 
      printf("Child(%d): Sent %d to parent.\n", pid, total); 
     } 
     else 
     { 
      printf("Child(%d): Error with len\n", pid); 
     } 
     _exit(0); 
    } 

    // parent process 
    pid = getpid(); 

    fpos = ((i*nums*5)/numchild); // 5 is the offset of the file values 

    // write to child process 
    printf("Parent(%d): Sending file position to child\n", pid); 
    write(fd[i][1], &fpos, sizeof(fpos)); 

    // wait for child responce 
    ret = select(2, &result_fd, NULL, NULL, &tm); 
    printf("\t\t%d\n", (FD_ISSET(results[0], &result_fd))); 
    if (FD_ISSET(results[0], &result_fd)) 
    { 
     ret = read(results[0], &total, sizeof(total)); 

     // output total 
     printf("Parent(%d): Recieved %d from child.\n", pid, total); 
     alltotal += total; 
    } 
} 
wait(0); 
gettimeofday(&stop, NULL); 
printf("\tTime elapsed: %lu microseconds\n", stop.tv_usec - start.tv_usec); 
} 

В нижней части, мой if (FD_ISSET(results[0], &result_fd)) никогда не возвращает ничего, кроме 0, я верю. Мне нужно его активировать, чтобы мой родитель суммировал дочерние суммы.

Вы видите, что не так?

+1

Попробуйте передать значение, большее, чем любое fd в вашем наборе (или просто 'FD_SETSIZE', как первый аргумент' select', а не номер 2. –

+0

@R .. это ничего не делает для меня. Родитель по-прежнему не выводит никаких итогов. – Tawm

+2

'tm = {.tv_sec = 0, .tv_usec = 1}'. Вы устанавливаете тайм-аут 'select' в 1 * микросекунду *. Так что, вероятно, это не так. – kaylum

ответ

0

Вам не хватает ошибок при проверке ошибок, что сделало бы почти невозможным сделать какие-либо выводы о том, что происходит.

  1. Вы не проверяете возвращаемые значения на fopen.
  2. Вы используете fseek и можете искать его в конце файла, и это не подведет. Вы также не проверяете, удалось ли fseek. См. Здесь некоторые подробности. fseek on a position beyond EOF does not trigger EOF using feof, how come?
  3. Почти ни один из ваших системных вызовов не проверен, чтобы убедиться, что они сработали.

Мы понятия не имеем, с чем вы скомпилировали это. Было ли это ...

НКУ -Wall -pedantic

он дал мне ошибки. Вы должны использовать Assert проверить ваши предположения, т.е.

fpos = ((i*nums*5)/numchild); 

Эта линия показалась мне производить очень большое количество, когда я запустил его с тестовым файлом, и если я seek'ed мимо конца файла, который я получил 0 в ответ, это ваша проблема?

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

+0

Я сделал большую часть этой проверки в предыдущих итерациях этой программы. 1) Я знаю, что 'fopen()' работает потому что мой дочерний процесс может суммировать коррекцию t сумму, которую он должен рассчитывать. 2) Даже если я дойду до последнего числа в файле, дочерний процесс просто добавит последний номер к его сумме. 3) Я просто использую 'gcc filename.c' и'./A.out' для запуска моей программы. Кроме того, я сделал изменения кода, такие как изменение аргументов в моем 'select()', например, изменение последнего аргумента на 'NULL' из' & tm', которое останавливает запуск детей одновременно. Else, родитель не может найти сумму своих сумм – Tawm

Смежные вопросы