我有一个我正在研究的程序,我使用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)?
select应该是第一个论点1+max_fd.虽然它可能pfd[CORES-1][0]是最大的,但不能保证.您可以在填充时计算最大的文件描述符read_set,并将其用于您的select调用.
此外,您需要read_set在select每次呼叫之前重新填充.所以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)