You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下用sendfile复制本地文件:需检查发送字节及截断目标文件吗?

关于Linux下sendfile复制文件的几个问题

当前用法是否安全?

不安全。你的代码直接调用一次sendfile就关闭文件描述符,但sendfile不保证一次性写完所有请求的字节——比如遇到信号中断(EINTR)、系统临时资源不足时,它会返回已经成功写入的字节数,而非请求的statBuf.st_size。这种情况下,最终的目标文件只会被写入部分数据,导致文件不完整。

是否需要循环检查返回值直到完成?

必须要。你需要循环调用sendfile,每次根据返回值更新已发送的字节数和剩余需要发送的字节数,直到全部数据写完,或者遇到不可恢复的错误。同时要注意处理EINTR错误:当sendfile返回-1且errno为EINTR时,应该重试调用,而非直接终止。

修正后的核心逻辑示例:

struct stat statBuf;
if (fstat(fdFrom, &statBuf) == -1) {
    // 处理fstat错误
    perror("fstat failed");
    close(fd);
    close(fdFrom);
    return -1;
}

off_t total_sent = 0;
const off_t file_size = statBuf.st_size;
ssize_t ret;

while (total_sent < file_size) {
    ret = sendfile(fd, fdFrom, NULL, file_size - total_sent);
    if (ret == -1) {
        if (errno == EINTR) {
            // 被信号中断,重试
            continue;
        }
        // 其他错误,处理后退出
        perror("sendfile failed");
        close(fd);
        close(fdFrom);
        return -1;
    }
    total_sent += ret;
}

close(fd);
close(fdFrom);

(注:这里sendfile的第三个参数用NULL,表示从源文件的当前偏移量继续读;如果需要指定起始偏移,应该用一个off_t*变量来跟踪)

复制前是否需要将目标文件截断为0长度?

取决于目标文件的打开方式:

  • 如果目标文件是新创建的(比如用open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)打开),O_TRUNC已经会自动将文件截断为0,不需要额外操作。
  • 如果目标文件已经存在且是用O_WRONLY或O_RDWR打开但没有O_TRUNC,那么直接写入会覆盖开头部分数据,但文件中未被覆盖的旧内容会保留,导致最终文件是新旧数据混合的错误状态。这种情况下,必须在复制前调用ftruncate(fd, 0)将目标文件截断为0长度,或者打开时加上O_TRUNC标志。

内容的提问来源于stack exchange,提问作者user1063364

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:40:01