写(2)是否总是写入小于或等于SSIZE_MAX?
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_MAX
或SIZE_MAX
。
类型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},则结果是实现定义的。
write()
的POSIX规范说:
如果
nbyte
的值大于{SSIZE_MAX},则结果是实现定义的。
因此,任何写入超过SSIZE_MAX
字节的尝试SSIZE_MAX
导致POSIX没有强制要求的行为,但必须由系统记录(它是实现定义的,而不是未定义的行为)。 但是,不同的系统可能会以不同的方式处理它,并且没有什么可以阻止一个系统报告错误(可能是errno
设置为EINVAL
)和另一个系统写入SSIZE_MAX
字节并报告该错误,将其留给应用程序再次尝试其余部分,以及其他系统系统可以是创造性的,也可以做不同的事情。
如果你有一个64位系统, SSIZE_MAX
可能大于世界上最大的单一数据中心的磁盘空间量(可能是一个数量级或更多,甚至允许NSA和谷歌),所以你不太可能遇到这个真正的问题,但在32位系统上,你可以轻松拥有超过2 GiB的空间,如果ssize_t
是32位,你必须处理所有这些。 (在Mac OS X 10.10.3上,32位版本具有4字节size_t
和ssize_t
,至少在默认情况下是这样。)
是的,可以在一次写入调用中写入的数据量仅限于ssize_t中可以保存的数据量。 有关说明,请参阅相关的glibc文档页面 。 引用该页面,“你的程序应该总是在循环中调用write,迭代直到写入所有数据。” (重点补充)该页面还阐明了ssize_t用于表示可以在单个操作中读取或写入的块的大小。