【问题标题】:fcntl()'s return value with F_GETFD flag?fcntl() 的返回值带有 F_GETFD 标志?
【发布时间】:2019-04-03 03:11:56
【问题描述】:

我在文件描述符上使用 fcntl() 并进行以下调用:

Retval = select(
    MaxSocketId + 1,
    &ReadSocketSet,
    (fd_set *)NULL,
    (fd_set *)NULL,
    (struct timeval *)NULL
);

if (Retval <= 0) {
    for (lIndexFD = 3; lIndexFD < (MaxSocketId + 1); lIndexFD++) {
        if ((lFlag = fcntl(lIndexFD, F_GETFD)) < 0) {
            if (errno == 9) {
                FD_CLR(lIndexFD, &ActiveSocketSet);
            }
        }
        else
            printf(" \n In fcntl Else cond %d ", lFlag);
    }
    continue;
}

但是我的进程在 fcntl() 的 else 条件下进入无限循环。 fcntl() 似乎返回 0。

我想知道它在什么情况下返回 0 以及如何处理这种情况。

【问题讨论】:

    标签: c linux sockets select fcntl


    【解决方案1】:

    更新:

    if (Retval &lt;= 0) 可能会更改为if (Retval &lt; 0)

    Retval 为零时,select 运行正常。

    Retval为-1且errno为EBADF时,使用fcntl检查fd是否有效。

    你看了fcntl它总是返回0,那是因为:

    1. 尚未设置 fd 的 FD_CLOEXEC 标志

    2. select 不会失败,fcntl 也不会失败,因为所有 fd 都是有效的。


    fcntl有多种cmd。使用F_GETFD 时,表示检索文件描述符标志。

    查看fcntl的手册,这种类型只有一个标志(FD_CLOEXEC)。所以如果不为 fd 设置这个标志,那么F_GETFD 将返回值 0。

    文件描述符标志

    以下命令操作与文件描述符关联的标志。目前,只定义了一个这样的标志:FD_CLOEXEC,close-on-exec 标志。如果 FD_CLOEXEC 位为 0,则文件 描述符将在 execve(2) 中保持打开状态,否则将关闭。

      F_GETFD (void)
             Read the file descriptor flags; arg is ignored.
    
      F_SETFD (int)
             Set the file descriptor flags to the value specified by arg.
    

    什么时候不返回0?

    1. open 一个文件时,FD_CLOEXEC 标志默认禁用。您可以像这样启用它。

      fd = open(filepath, O_RDONLY | O_CLOEXEC)
      
    2. 调用fcntl(fd, F_SETFD, FD_CLOEXEC)启用标志FD_CLOEXEC

    【讨论】:

    • 如果 fcntl() 返回
    • 另外,为什么在这种情况下禁用它?因为在这里我没有打开任何文件。我在 sock fd 上调用 bind(),然后是 listen(),然后 select() 来检查它是否准备好接受连接。
    • 不,我的意思是当 fcntl() 为 fd 返回值 =0 时,我是否应该使用 FD_CLR 从我的 fd_set 中清除 fd,就像我在 errno=9 (EBADF) 情况下所做的那样
    • socket 功能相同,默认FD_CLOEXEC 被禁用。您可以像这样启用它。 socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0),或在accept4 函数中accept4(fd, addr, len, SOCK_CLOEXEC)。使用命令man socket,同样查看手册。
    • @arjungaur 我现在明白了。当errno=9,那么你需要清除它。在您的情况下,它不是关于设置或获取F_CLOEXEC,它只是在选择失败时检查 fd 是否仍然有效。
    猜你喜欢
    • 1970-01-01
    • 2022-08-13
    • 2011-09-01
    • 2010-09-28
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2015-05-16
    相关资源
    最近更新 更多