【问题标题】:linux fcntl - unsetting flaglinux fcntl - 取消设置标志
【发布时间】:2010-09-28 03:43:41
【问题描述】:

如何使用 fcntl 取消设置已设置的标志?

例如我可以使用

将套接字设置为非阻塞模式
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)

现在,我想取消设置 O_NONBLOCK 标志。

我试过 fcntl(sockfd, F_SETFL, flags | ~O_NONBLOCK)。它给了我错误 EINVAL

【问题讨论】:

  • 试试flags & ~O_NONBLOCK。即&,而不是|。
  • 是的,你是对的。复制粘贴问题。 :-)。编码时需要思考。

标签: linux fcntl


【解决方案1】:
int oldfl;
oldfl = fcntl(sockfd, F_GETFL);
if (oldfl == -1) {
    /* handle error */
}
fcntl(sockfd, F_SETFL, oldfl & ~O_NONBLOCK);

未经测试,但希望这会有所帮助。 :-)

【讨论】:

  • 当然。也阅读我对您的问题的评论。也就是说,除非您在编辑中出现拼写错误,否则您必须使用 & 来清除标志,而不是 |。
  • 丹尼尔感谢您指出这一点。有时我认为像这样大量无用的错误检查会阻碍新程序员在实际需要的地方进行重要的错误检查。
  • @DanielTrebbien:错了。只有非错误值不是负数。 fcntl(fd, F_GETFL) 可能会失败,即它可以返回 -1,例如 invalid fd may cause EBADF
  • @J.F.Sebastian:糟糕,我的错。你是对的。事实上,the spec 表示“否则,应返回 -1 并设置 errno 以指示错误。”并举个例子:flags = fcntl(fd, F_GETFD); if (flags == -1) /* Handle error */;Chris,希望你不要介意,但我恢复了你原来的代码。
【解决方案2】:

尝试取消设置所有标志:

fcntl(sockfd, F_SETFL, 0);

另外,用~O_NONBLOCK 对标志进行或运算也没用,您需要对它进行“与”运算,因为您想要的是取消设置 O_NONBLOCK 位。

【讨论】:

  • 如果您只想取消设置非阻塞标志,则取消设置所有标志有点矫枉过正。 :-)
【解决方案3】:
val = fcntl(fd, F_GETFL, 0);
flags = O_NONBLOCK;
val &= ~flags;
fcntl(fd,F_SETFL,val);

如果你这样做,已经设置的 O_NONBLOCK 将被取消设置。 在这里,flags 包含您要取消设置的标志。 完成 AND(&) 操作后,您必须再次使用 val 中的值设置标志。 我希望这会对你有所帮助。

【讨论】:

    【解决方案4】:

    以下代码将取消设置标志,例如 O_NONBLOCK 标志:

    if ((flags = fcntl(fileno(sockfd), F_GETFL, 0)) < 0) {
        perror("error on F_GETFL");
    }
    else {
        flags &= ~O_NONBLOCK;
        if (fcntl(fileno(sockfd), F_SETFL, flags) < 0) {
            perror("error on F_SETFL");
        }
        else {
            /* O_NONBLOCK set without errors. continue from here */
            }
    }
    

    问候

    【讨论】:

      猜你喜欢
      • 2018-12-13
      • 1970-01-01
      • 2011-09-01
      • 2016-10-20
      • 1970-01-01
      • 2019-04-03
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多