C使用select并从管道读取

and*_*pcg 2 c select pipe

我有一个我正在研究的程序,我使用select来从管道中进行选择.

问题是我正在使用if(FD_ISSET(pfd[i][0], &read_set))并且它验证失败,因为FD_ISSET返回0,但是如果我尝试使用read(pfd[i][0],&c,sizeof(c))它,它将正常工作并且管道pfd [0]中的内容与pfd [1]不同,就像我想要的那样.

我想知道到底发生了什么,因为FD_ISSET返回0但我实际上可以从中读取内容

编辑

全局变量CORES将控制我创建的进程数量下一个代码将创建管道并使用FD_SET来设置位

for(i=0; i<CORES; i++)
{
    if(pipe(pfd[i])==-1)
        perror("Ocorreu um erro a criar um pipe");

    FD_SET(pfd[i][0], &read_set);
}
Run Code Online (Sandbox Code Playgroud)

read_set是在main()启动后立即定义的.我在上面的代码之后使用for()来使用fork()创建x进程(x = CORES)

然后这部分在父进程中运行:

    while (x<CORES){
    int selec = select(pfd[CORES-1][0]+1, &read_set, NULL, NULL, NULL);

    if(selec>0)
    {
        if(FD_ISSET(pfd[x][0], &read_set))
        {
            close(pfd[x][1]);

            if(read(pfd[x][0],&c,sizeof(c))==-1)
                perror("Ocorreu um erro a ler do pipe");

            printf("c= %f \n",c);
            c_final+=c;
            x++;
        }
        else
            printf("\nFile descriptor pfd[%d][0] is not set\n",x);

    }
    else if(selec == -1)
        perror("Ocorreu um erro no select");
}
Run Code Online (Sandbox Code Playgroud)

这个问题是FD_ISSET(pfd[x][0], &read_set)不会通过,因为它没有为pfd [0]设置,但它可以用于pfd [1],反之亦然(因为我不知道它是否会因0或1而失败)

EDIT2:

select()为read_set中的文件描述符数返回一个int.我将CORES设置为2,因此它创建了2个进程和2个管道,并在read_set中设置了2位.我的select()返回int 1.它是否应该返回int 2或0计数(所以它将是0和1 = 2)?

vha*_*lac 5

select应该是第一个论点1+max_fd.虽然它可能pfd[CORES-1][0]是最大的,但不能保证.您可以在填充时计算最大的文件描述符read_set,并将其用于您的select调用.

此外,您需要read_setselect每次呼叫之前重新填充.所以while循环之外的for循环需要进来.实际上,最好将select移到外面,然后用for循环开始封闭块,并read_set在while循环之后在另一个循环中结束 - 这样每次选择返回,您可以处理所有已发信号的描述符,而无需再次进入选择.


编辑:澄清我对循环的意义:每次选择返回时都应该检查所有描述符.但是你不能只选择一次选择,因为不能保证一次就能准备好所有答案.所以你做的事情如下:

for (i=0; i != CORES; ++i)
{
  // Call pipe() and populate pfd[i]
}

while (!finished) // Need a proper condition to terminate this loop
{
    // Setup read_set
    FD_ZERO(&read_set);
    for (i=0; i != CORES; ++i)
    {
        FD_SET(pfd[i][0], &read_set);
        // find max_fd here
    }
    // select here
    if (select(max_fd+1, blahblah) > 0)
    {
        for (i=0; i != CORES; ++i) // This used to be while(x < CORES). But a for loop would do
        {
            // Check the fd, and process
        }
    }
    else
    {
         // error in select
    }
}
Run Code Online (Sandbox Code Playgroud)