【问题标题】:system call return values and errno系统调用返回值和errno
【发布时间】:2012-10-07 07:00:09
【问题描述】:

我在我的程序中使用以下系统调用:

recvfrom
sendto
sendmsg

从上面提到的每个系统调用中,我检查它是否在没有任何中断的情况下完成,如果它被中断,我会重试。

例如:

recvagain:     
    len = recvfrom(fd, response, MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
    if (errno == EINTR) {
           syslog(LOG_NOTICE, "recvfrom interrupted: %s", strerror(errno));
           goto recvagain;
    }

这里的问题是每次失败时我是否需要将 errno 值重置为 0。或者如果recvfrom() 成功,是否将errno 重置为0?

recvfrom() 手册页说:

成功完成后,recvfrom() 以字节为单位返回消息的长度。如果没有可接收的消息并且 peer 执行了有序的关闭,recvfrom() 返回 0。 否则,函数返回 -1 并设置 errno 以指示 错误。

sendto 和 sendmsg 的情况相同。

我现在无法真正检查这个,因为我无权访问服务器-客户端设置。 有什么想法吗?

谢谢

【问题讨论】:

    标签: c linux operating-system system-calls systems-programming


    【解决方案1】:

    recvfrom 如果被中断则返回-1(并将errno 设置为EINTR)。因此,您应该检查len

    if(len == -1) {
        if(errno == EINTR) {
            syslog(LOG_NOTICE, "recvfrom interrupted");
            goto recvagain;
        } else {
            /* some other error occurred... */
        }
    }
    

    【讨论】:

    • 好的,我会这样做的,那么 errno 呢?你的意思是说如果系统调用成功它就不会被重置,对吗?
    • errno 只有在函数返回指示错误的值时才能被信任。否则,它可能毫无意义。
    【解决方案2】:

    errno 伪“变量”在成功的系统调用上可能不会改变。因此,您可以在 recvfrom 之前清除它,或者在 len<0 测试它的值时清除它。

    请参阅errno(3) 手册页了解更多信息。

    实际上,正如 Robert Xiao (nneonneo) 所评论的,您不应该编写 errno 并在系统调用失败时对其进行测试(在这种情况下,C 函数 - 例如 recvfrom 等...- 包装该系统调用在返回-1之前会写errno)。

    【讨论】:

    • 你很少需要清除errno;我不认为这是其中之一。
    • 清除errno 的原因是为了覆盖以前(不久前)由不相关的系统调用设置的情况。
    • 你通常不应该关心。正如我在回答中指出的那样,正确的解决方案是检查 len 以查看是否确实发生了错误。
    • @BasileStarynkevitch 但通常不需要,因为您应该始终检查返回值在查看errno之前。仅当调用指示错误条件的值(例如,getpriority(2) 为 -1,readdir(3) 为 NULL)也是来自函数的有效响应(nice value -1 或 end of directory流,分别)。
    猜你喜欢
    • 1970-01-01
    • 2016-09-07
    • 2012-02-11
    • 2011-08-06
    • 1970-01-01
    • 2012-03-10
    • 2014-12-10
    • 2012-05-07
    • 2013-01-24
    相关资源
    最近更新 更多