选择仅检查fds直到255,直到FD_SETSIZE [英] select only checks fds till 255 not till FD_SETSIZE

查看:146
本文介绍了选择仅检查fds直到255,直到FD_SETSIZE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

时,不检查fd是否打开.这是我的示例代码:

select on fds higher then 255 do not check if the fd is open. Here is my example code:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/select.h>

int main()
{
    fd_set set;
    for(int i = 5;i<FD_SETSIZE;i++)
    {
        printf("--> i is %d\n", i);
        FD_ZERO(&set);
        FD_SET(i, &set);
        close(i);

        int retval = select(FD_SETSIZE, &set, NULL, NULL, NULL);
        if(-1 == retval)
        {
            perror("select");
        }
    }
}

结果是:

--> i is 5
select: Bad file descriptor
...
--> i is 255
select: Bad file descriptor
--> i is 256

然后阻止该应用程序. 为什么直到FD_SETSIZE都不会在256上创建EBADF?

Then the application blocks. Why does this not create a EBADF on 256 till FD_SETSIZE?

从评论中请求的信息:

prlimit的结果是:

NOFILE     max number of open files                1024   1048576

这是strace ./test_select的结果:

select(1024, [127], NULL, NULL, NULL)   = -1 EBADF (Bad file descriptor)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x8402 (flags O_RDWR|O_APPEND|O_LARGEFILE)
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
write(3, "select: Bad file descriptor\n", 28select: Bad file descriptor
) = 28
close(3)                                = 0
write(1, "--> i is 128\n", 13--> i is 128
)          = 13
close(128)                              = -1 EBADF (Bad file descriptor)
select(1024, [128], NULL, NULL, NULL

从评论中揭穿思想:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/select.h>
#include <fcntl.h>

int main()
{
    char filename[80];
    int fd;
    for(int i = 5;i<500;i++)
    {
        snprintf(filename, 80, "/tmp/file%d", i);
        fd = open(filename, O_RDWR | O_APPEND | O_CREAT);
    }
    printf("--> fd is %d, FD_SETSIZE is %d\n", fd, FD_SETSIZE);
    fd_set set;
    FD_ZERO(&set);
    FD_SET(fd, &set);
    int retval = select(FD_SETSIZE, NULL, &set, NULL, NULL);
    if(-1 == retval)
    {
        perror("select");
    }
}

结果:

$ ./test_select
--> fd is 523, FD_SETSIZE is 1024

进程正常退出,没有阻塞.

Process exits normally, no blocking.

推荐答案

这里发生了非常奇怪的事情.您也许在Linux内核中发现了一个错误.

Something very strange is going on here. You may have found a bug in the Linux kernel.

我修改了您的测试程序,使其更加精确,并且在遇到问题时也不会卡住:

I modified your test program to make it more precise and also to not get stuck when it hits the problem:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>

int main(void)
{
    fd_set set;
    struct timeval tv;
    int i;

    for(i = 5; i < FD_SETSIZE; i++)
    {
        FD_ZERO(&set);
        FD_SET(i, &set);

        tv.tv_sec = 0;
        tv.tv_usec = 1000;

        close(i);
        int retval = select(FD_SETSIZE, &set, 0, 0, &tv);
        if (retval == -1 && errno == EBADF)
          ;
        else
        {
            if (retval > 0)
                printf("fd %d: select returned success (%d)\n", i, retval);
            else if (retval == 0)
                printf("fd %d: select timed out\n", i);
            else
                printf("fd %d: select failed (%d; %s)\n", i, retval, strerror(errno));
            return 1;
        }
    }
    return 0;
}

我对POSIX的理解是,无论FD_SETSIZE是什么,该程序都不会产生任何输出并成功退出.这就是它在FreeBSD 11.1和NetBSD 7.1(两者都在某些描述的x86处理器上运行)上所做的工作.但是在Linux(x86-64,内核4.13)上,它可以打印

My understanding of POSIX says that, whatever FD_SETSIZE is, this program should produce no output and exit successfully. And that is what it does on FreeBSD 11.1 and NetBSD 7.1 (both running on x86 processors of some description). But on Linux (x86-64, kernel 4.13), it prints

fd 256: select timed out

并成功退出.甚至更陌生,如果我在strace下运行相同的二进制文件,则会更改输出:

and exits unsuccessfully. Even stranger, if I run the same binary under strace, that changes the output:

$ strace -o /dev/null ./a.out
fd 64: select timed out

即使我不告诉gdb要做 除了运行程序以外的任何事情,如果我在gdb下运行它,也会发生同样的事情.

The same thing happens if I run it under gdb, even if I don't tell gdb to do anything other than just run the program.

Reading symbols from ./a.out...done.
(gdb) r
Starting program: /tmp/a.out 
fd 64: select timed out
[Inferior 1 (process 8209) exited with code 01]

所以某些事情正在发生变化,只是因为该过程受ptrace监视.那只能由内核引起.

So something is changing just because the process is subject to ptrace monitoring. That can only be caused by the kernel.

我已经提交了关于Linux内核的错误报告,并将报告他们怎么说.

I have filed a bug report on the Linux kernel and will report what they say about it.

这篇关于选择仅检查fds直到255,直到FD_SETSIZE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆