信号在阻塞模式下中断发送方法

时间:2015-07-01 09:22:04

标签: c sockets

我使用处于阻止模式的套接字进行编程,我对send方法有疑问。

send方法的手册页中,它说:

  

[EINTR]信号在传输任何数据之前中断系统调用。

这意味着如果信号在传输任何数据之前中断系统调用,send将返回-1,errno将设置为EINTR

我的问题是,如果在信号中断系统调用时传输了一部分数据,那么将返回什么。它似乎不应该返回-1,因为它已经发送了一些数据。我认为它将返回已传输的数据的数量,这意味着阻塞模式下的send方法可能返回的数据量少于您作为第三个参数传递的数据。

ssize_t send(int socket, const void *buffer, size_t length, int flags);

3 个答案:

答案 0 :(得分:2)

documentation很清楚。

  

返回值

     

成功时,这些调用返回发送的字节数。出错时,返回-1,并正确设置errno。

     

[...]

     

EINTR 在传输任何数据之前发生信号;

send()要么返回

  • 发送的字节数
  • -1

如果返回-1,则会通过errno的值显示原因。

如果errno等于EINTR,则信号中断send(),而目前尚未收到任何数据

从上面的这些信息中可以得出结论,如果收到数据,send()函数将返回-1,无论是否是否收到了信号。

答案 1 :(得分:2)

其他答案非常清楚,但在阅读了一些评论后,我想补充一些其他信息。

首先,你明白了EINTR背后的想法。被系统调用中的信号中断不会被视为错误。慢速系统调用中EINTR背后的基本原理(慢速系统调用是那些可以永久阻止的系统调用,例如某些文件类型上的open(2) - 例如终端设备 - accept(2)read(2)和{ {1}}在某些设备上 - 包括套接字等)是如果您的程序在系统调用中被阻塞并且信号被捕获(但仍被阻止),那么很可能(但不是强制性的)信号处理程序已更改在您的程序中状态和事物是不同的,因此调用会在write(2)过早返回,以便您有机会做任何您可能想要做的事情。它不是EINTREINVAL或其他“真实”错误的错误 - 它只是内核告诉您信号被捕获的方式。

如果您不想做任何事情,那么在设置信号处理程序时会在EBADF SA_RESTART字段上设置sa_flags标志(这会导致系统调用自动重新启动),或在struct sigaction设置为send(2)时返回-1时再次显式调用errno

最重要的是,内核没有固有的限制,强制它在捕获信号时返回用户空间。相反,EINTR只是开发人员可能会觉得有用的一种方便行为。

如果内核正在传输数据并且发出信号,那就没什么大不了的:如果正在传输数据,那么系统调用正在取得进展。内核正在进程上下文中代表调用它的程序执行一个系统调用,所以从技术上讲,该进程不再处于休眠状态。如果信号到达,它将处于待处理状态,直到内核确定是时候将其传递给进程 - 最有可能的是,这会在EINTR返回时发生。

答案 2 :(得分:-1)

  

[EINTR]信号在传输任何数据之前中断系统调用。

这意味着如果send()开始传输数据,它将不会被任何信号中断。因此,传输将阻止信号的接收,直到它完成。 send()可能返回的数据字节数少于作为第三个参数传递的数据字节的情况通常是由于网络问题(例如数据包丢失)造成的。