Select()永远不会返回true

时间:2016-03-12 05:13:57

标签: c select pipe fork

我试图从父级到子级使用pipe()来对文件的各个部分求和。孩子们在档案中获得一个职位,将他们指定的数字相加,发回他们的金额,并且父母将孩子的总和加起来。

我父母部分的代码存在问题,以便在孩子完成后阅读。

代码:

#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 个答案:

答案 0 :(得分:0)

你错过了很多错误检查,这使得几乎无法得出有关正在发生的事情的任何结论。

  1. 您没有检查fopen上的返回值。
  2. 您正在使用fseek,它可以搜索文件的末尾并且不会失败。您也没有检查fseek是否成功。请看这里了解一些细节。 fseek on a position beyond EOF does not trigger EOF using feof, how come?
  3. 几乎没有系统调用被检查以查看它们是否有效。
  4. 我们不知道你用这个编译了什么。是这个......

    gcc -Wall -pedantic

    它给了我错误。您应该使用assert来检查您的假设,即

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

    当我用测试文件运行它时,那条线看起来产生了一个非常大的数字,如果我在文件的末尾寻找,我在回报中得到0,这是你的问题吗?

    在你认为不应该发生某些事情的地方用你的断言加密你的代码,即测试所有不变量,无论它们看起来多么愚蠢。断言和printf很简单,但它们非常有效。