捕获SIGALRM后,为什么recvfrom()仍会阻塞?

捕获SIGALRM后,为什么recvfrom()仍会阻塞?,c,linux,unix,networking,network-programming,C,Linux,Unix,Networking,Network Programming,我想使用alarm()设置recvfrom的超时时间。但是发现当使用signal()为SIGALRM注册处理程序时,SIGALRM已被捕获,然后调用信号处理程序。但是从处理程序返回后,recvfrom()仍然会阻塞,而没有数据到来,也没有EINTR错误。为什么?signal()是否自动设置了SA_RESTART标志? 代码如下: signal(SIGALRM, sig_handler); while(1) { alarm(5); n = recvfrom(sock, buf, B

我想使用
alarm()
设置
recvfrom
的超时时间。但是发现当使用
signal()
SIGALRM
注册处理程序时,
SIGALRM
已被捕获,然后调用信号处理程序。但是从处理程序返回后,
recvfrom()
仍然会阻塞,而没有数据到来,也没有
EINTR
错误。为什么?
signal()
是否自动设置了
SA_RESTART
标志? 代码如下:

signal(SIGALRM, sig_handler);
while(1)
{
    alarm(5);
    n = recvfrom(sock, buf, BUF_MAX, 0, (struct sockaddr*)&addr, &len);
    if(n < 0)
    {
        if(errno == EINTR)
        {
            printf("recvfrom timeout\n");
            continue;
        }
        else
        {
            printf("recvfrom error\n");
        }
    }
    else
    {
         printf("data: %s\n", buf);
         alarm(0);
    }
}

void sig_handler(int signo)
{
    return;
}
信号(信号处理器、信号处理器);
而(1)
{
警报(5);
n=recvfrom(sock、buf、buf_MAX、0、(struct sockaddr*)和addr、&len);
if(n<0)
{
如果(errno==EINTR)
{
printf(“recvfrom超时\n”);
继续;
}
其他的
{
printf(“recvfrom错误\n”);
}
}
其他的
{
printf(“数据:%s\n”,buf);
报警(0);
}
}
无效信号处理器(int signo)
{
返回;
}

根据
信号
的手册页,阻塞呼叫是否重新启动是一个平台相关属性:

Linux上的情况如下:

  • 内核的signal()系统调用提供SystemV语义
  • 默认情况下,在glibc2及更高版本中,signal()包装函数不调用内核系统调用。相反,它使用提供BSD的标志调用sigaction(2) 语义学。只要定义了合适的功能测试宏,就会提供此默认行为:_BSD_glibc 2.19及更早版本上的源代码或_default_中的源代码 glibc 2.19及更高版本。(默认情况下,已定义这些宏;有关详细信息,请参阅功能测试宏(7))。如果未定义此类功能测试宏,则信号() 提供SystemV语义
因为BSD语义相当于使用以下标志调用
sigaction(2)

sa.sa_flags = SA_RESTART;

System V semantics不会重新启动,您看到的是您的程序正在以BSD方式运行,因此您应该确保使用上述功能测试宏来定义程序的行为。

真正的问题是为什么不使用so_RCVTIMEO?