【问题标题】:reentrant function read()可重入函数 read()
【发布时间】:2011-04-09 10:28:53
【问题描述】:

我找到了select() 的服务器,我想从一些客户端接收它。

但我发现服务器会被 gdb 在read() 中阻止。

所以我想通过添加SIGALRM 来解决它,但是 当发生超时时,它仍然在read() 中被阻止。

发生这种情况是因为系统调用会自动重新启动,read() SIGALRM 信号处理程序返回时不会中断。

这个解释正确吗?

【问题讨论】:

    标签: c linux networking


    【解决方案1】:

    解决这个问题的通常方法是使用SOCK_NONBLOCK to socket(2)O_NONBLOCK to fcntl(2)F_SETFL 命令。一旦套接字被标记为非阻塞,当您尝试从中读取时它永远不会阻塞,并且您无需尝试跨越阻塞或非阻塞之间的鸿沟。你确定select(2) 设置文件描述符吗? select(2) 联机帮助页确实描述了您看到所见内容的一个原因,但似乎不太可能:

    在 Linux 下,select() 可能会将套接字文件描述符报告为 “准备阅读”,尽管随后的阅读 块。例如,这可能在数据到达时发生 但经检查有错误的校验和并被丢弃。 可能存在文件描述符在其他情况下 虚假地报告为准备就绪。因此使用起来可能更安全 O_NONBLOCK 在不应阻塞的套接字上。

    如果您真的只是想阻止自动重启,请查看sigaction(2) 中的SA_RESTART 以防止可重启的系统调用重启。

    【讨论】:

    • 我以这种方式使用 select():select( FD_SETSIZE, server->fd_readset, 0, 0, timeout ) ,我使用 FD_SETSIZE,这可以吗?或者这会产生一些错误?谢谢
    • @lxgeek - 不要在那里使用 FD_SETSIZE。它为您提供 fd_set 的大小,通常为 1024。select 的第一个参数需要最高的文件描述符 + 1。自己跟踪。使用 FD_SETSIZE 会强制搜索一千个您可能永远不会使用的 FD。它会起作用,但效率低下。你也想通过“&timeout”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2011-02-07
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多