C语言 允许请求size_t但仅ssize_t结果的系统调用的基本原理



考虑:

ssize_t write(int fd, const void *buf, size_t count);

结果必须签名以说明错误等时的-1,因此ssize_t。 但是,当请求超过ssize_t的结果未定义时,为什么要允许请求是未签名的金额(两倍大(呢?

由于

不检查 count 参数的符号性,内核中是否有重大优化? 还是别的什么?

根据ssize_t write(int fildes, const void *buf, size_t nbyte)的文档

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

因此,每个特定的实现可能会以不同的方式处理这种情况。如果某些实现只是设置EFBIG,我不会感到惊讶。

至于基本原理,也许size_t只是在语义上表示缓冲区大小的最佳类型?它指出这个参数是一个非负大小,没有别的。

我认为这很好,因为size_tsizeof运算符返回的值的类型,这允许这样的调用:

char buffer[1 << 20];
ssize_t wrote;
wrote = write(fd, buffer, sizeof buffer);

如果函数采用已签名版本,则需要强制转换。此外,正如其他人指出的那样,像这样的语义函数不能接受负值,因此接受它们没有多大意义。

通过使参数无符号,它消除了函数检查无意义的负面请求的需要。

write只能从单个连续的unsigned char数组写入,该数组不能大于PTRDIFF_MAX,这是(在所有现实世界的POSIX系统上,也许POSIX也需要...?(等于SIZE_MAX/2。因此,传递一个如果解释为有符号值将为负值的值首先是一个编程错误 - 传递的大小与缓冲区中的可用空间不一致。

理论上,readvwritev 可以通过在数组中多次重复相同的iov缓冲区来执行大于 SIZE_MAX/2 的 IO 操作,但如果我没记错的话,如果总大小大于 SSIZE_MAX,它们被指定为失败。

最新更新