Linux fcntl - 取消设置标志

9

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

例如,我可以使用以下方式将套接字设置为非阻塞模式:

fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)

现在,我想取消 O_NONBLOCK 标志。 我尝试使用 fcntl(sockfd, F_SETFL, flags | ~O_NONBLOCK)。但是它给了我一个 EINVAL 错误。

2
尝试使用 flags & ~O_NONBLOCK,即使用 &,而不是 |。 - C. K. Young
是的,你说得对。复制、粘贴问题。:-) 写代码时需要思考。 - chappar
4个回答

8
int oldfl;
oldfl = fcntl(sockfd, F_GETFL);
if (oldfl == -1) {
    /* handle error */
}
fcntl(sockfd, F_SETFL, oldfl & ~O_NONBLOCK);

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

1
当然。请阅读我的评论,特别是如果您在编辑中没有打错字,那么必须使用&来清除标志,而不是|。 - C. K. Young
Daniel,感谢你指出这一点。有时我认为过多的无用错误检查会让新手程序员对实际需要进行重要错误检查的地方感到沮丧。 - R.. GitHub STOP HELPING ICE
1
@DanielTrebbien:错误的。只有非错误值才不是负数。fcntl(fd,F_GETFL)可能会失败,即它可以返回-1,例如,无效的fd可能会导致EBADF - jfs
1
@J.F.Sebastian:糟糕,我的错误。你是正确的。实际上,规范说:“否则,将返回-1并设置errno以指示错误。”并给出了一个例子:flags = fcntl(fd, F_GETFD); if (flags == -1) /* 处理错误 */; Chris,希望你不介意,但我恢复了你的原始代码。 - Daniel Trebbien

3
val = fcntl(fd, F_GETFL, 0);
flags = O_NONBLOCK;
val &= ~flags;
fcntl(fd,F_SETFL,val);

如果您这样做,已设置的 O_NONBLOCK 将被取消设置。在这里,flags 包含您要取消设置的标志。完成 AND(&) 操作后,您需要使用val中的值重新设置标志。我希望这能帮到您。

1
以下代码将取消一个标志,例如 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 */
        }
}

敬礼


0

尝试取消所有标志:

fcntl(sockfd, F_SETFL, 0);

同时,使用 ~O_NONBLOCK 进行 OR 操作没有任何作用,你需要进行 AND 操作,因为你想要取消设置 O_NONBLOCK 位。


如果您只想取消非阻塞标志,则取消所有标志有点过度了。 :-) - C. K. Young

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接