写(2)是否总是写入小于或等于SSIZE_MAX?

时间:2015-04-18 21:20:41

标签: c posix

write(2)的功能签名是ssize_t write(int fd, const void *buf, size_t count)。通常,size_t的最大值大于ssize_t的最大值。这是否意味着write实际可以写入的数据实际上是SSIZE_MAX而不是SIZE_MAX?如果不是这种情况,当写入的字节数相对于溢出大于SSIZE_MAX时会发生什么?

我基本上想知道write写的数据量是否受SSIZE_MAXSIZE_MAX限制。

3 个答案:

答案 0 :(得分:15)

类型ssize_t由POSIX定义为签名类型,能够存储至少32767(_POSIX_SSIZE_MAX)而没有其他保证。因此,其最大值可能小于size_t的最大值。

ssize_t的POSIX定义:

ssize_t
     

用于计算字节数或错误指示。

因此,您请求写入的字节数可能大于ssize_t可以容纳的字节数。在这种情况下,POSIX将其留给实现。

来自write()的POSIX规范:

ssize_t write(int fildes, const void *buf, size_t nbyte);
     

如果nbyte的值大于{SSIZE_MAX},           结果是实现定义的。

答案 1 :(得分:13)

write()的POSIX规范说:

  

如果nbyte的值大于{SSIZE_MAX},则结果是实现定义的。

因此,任何写入超过SSIZE_MAX字节的尝试都会导致POSIX没有强制要求的行为,但必须由系统记录(它是实现定义的,而不是未定义的行为)。但是,不同的系统可能会以不同的方式处理它,并且没有什么可以阻止一个系统报告错误(可能errno设置为EINVAL)和另一个写SSIZE_MAX字节和报告然后,将其留给应用程序再次尝试其余部分,其他系统可能具有创造性,并且还可以做不同的事情。

如果你有一个64位系统,SSIZE_MAX可能比世界上最大的单一数据中心的磁盘空间量大(可能是一个数量级或更多,甚至允许使用NSA和Google),因此您不太可能遇到此问题,但在32位系统上,您可以轻松拥有超过2 GiB的空间,如果ssize_t是32位,你必须处理这一切。 (在Mac OS X 10.10.3上,32位版本具有4字节size_tssize_t,至少在默认情况下是这样。)

答案 2 :(得分:2)

是的,可以在一次写入调用中写入的数据量仅限于ssize_t中可以保存的数据量。有关说明,请参阅the relevant glibc documentation page。要引用该页面,"您的程序应始终在循环中调用write,迭代直到写入所有数据。" (重点补充)该页面还阐明了ssize_t用于表示可以在单个操作中读取或写入的块的大小。