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
限制。
答案 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_t
和ssize_t
,至少在默认情况下是这样。)
答案 2 :(得分:2)
是的,可以在一次写入调用中写入的数据量仅限于ssize_t中可以保存的数据量。有关说明,请参阅the relevant glibc documentation page。要引用该页面,"您的程序应始终在循环中调用write,迭代直到写入所有数据。" (重点补充)该页面还阐明了ssize_t用于表示可以在单个操作中读取或写入的块的大小。