gpt4 book ai didi

c - 处理不完整的 write() 调用

转载 作者:IT王子 更新时间:2023-10-29 00:24:37 26 4
gpt4 key购买 nike

在 Linux/Unix 中,write() 调用最终写入的字节数可能少于请求的字节数:

The number of bytes written may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the call was interrupted by a signal handler after having written less than count bytes. (See also pipe(7).)

C 标准库的 fwrite() 具有相同的行为。我见过的大多数代码都忽略了这种可能性,选择以下列方式处理错误:

int ret = write(fd, buf, size);
if (ret < 0) {
printf("Couldn't write %s: %s\n", path, strerror(errno));
exit(1);
}

我个人养成了修改条件的习惯,以便我们进行检查

if (ret != size) {
printf("Couldn't write %s: %s\n", path, strerror(errno));
exit(1);
}

它注意到了这种情况。但是,我也注意到我的程序偶尔会退出:

Couldn't write /some/file: Success

我想这并不奇怪。但是,处理这种情况的标准、健壮、干净的方法是什么?显然,“静默数据损坏”——这似乎是每个教程的行为——是不对的。我可以修改我的代码,使其专门检测这种情况并退出。

但是man 2 write中提供的例子只是一个例子。还有其他例子可以重试吗(EINTR 就是一个例子......)?我如何检测这些,更重要的是,确保我处理了每一个案例?难道没有一种标准的简洁方法来制作这些错误处理程序吗?

最佳答案

如果在两种情况下什么都不写,Write 将返回一个负数:

  • 临时错误(例如EINTREAGAINEWOULDBLOCK);第一个可以发生在任何写入中,后两个(广泛地)只发生在非阻塞 I/O 上。

  • 永久性错误。

通常你会想重试第一个,所以例程是在返回 EINTREAGAINEWOULDBLOCK 时重复写入(尽管我见过反对后者的论点)。

例如:

ssize_t
write_with_retry (int fd, const void* buf, size_t size)
{
ssize_t ret;
do
{
ret = write(fd, buf, size);
} while ((ret<0) && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
return ret;
}

另请注意(来自手册页)在非阻塞 I/O 或阻塞 I/O 的情况下,write 可以返回少于您请求的字节数(正如 linux 手册页所述) .

OS-X 手册页摘录:

When using non-blocking I/O on objects, such as sockets, that are subject to flow control, write() and writev() may write fewer bytes than requested; the return value must be noted, and the remainder of the operation should be retried when possible.

Linux 手册页摘录(我的重点):

The number of bytes written may be less than count if, for example, there is insufficient space on the underlying physical medium, or the RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the call was interrupted by a signal handler after having written less than count bytes.

您通常会使用 select() 处理这些情况,但要手动处理这种情况:

ssize_t
write_with_retry (int fd, const void* buf, size_t size)
{
ssize_t ret;
while (size > 0) {
do
{
ret = write(fd, buf, size);
} while ((ret < 0) && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
if (ret < 0)
return ret;
size -= ret;
buf += ret;
}
return 0;
}

关于c - 处理不完整的 write() 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32683086/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com