我需要使用sendfile64来复制大约16GB的文件。 我迄今取得的成绩是
#include <unistd.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <sys/sendfile.h> #include <sys/stat.h> int main (int argc, char** argv) { long long src; long long dest; struct stat64 stat_buf; off64_t offset = 0LL; long long rc; if (argc != 3) { fprintf(stderr, "usage: %s <source> <destination>\n", argv[0]); exit(1); } src = open64(argv[1], O_RDONLY); if (src == -1) { fprintf(stderr, "unable to open '%s': %s\n", argv[1], strerror(errno)); exit(1); } fstat64(src, &stat_buf); dest = open64(argv[2], O_WRONLY|O_CREAT, stat_buf.st_mode); if (dest == -1) { fprintf(stderr, "unable to open '%s': %s\n", argv[2], strerror(errno)); exit(1); } /* copy file using sendfile */ rc = sendfile64 (dest, src, &offset, stat_buf.st_size); if (rc == -1) { fprintf(stderr, "error from sendfile: %s\n", strerror(errno)); exit(1); } if (rc != stat_buf.st_size) { fprintf(stderr, "incomplete transfer from sendfile: %lld of %lld bytes\n", rc, (long long)stat_buf.st_size); exit(1); } /* clean up and exit */ close(dest); close(src); return 0; }
我已经编译使用
g++ BigCopy2.cpp -o BigCopy2 -D_FILE_OFFSET_BITS=64 -DLARGEFILE64_SOURCE
问题是我仍然无法复制超过2GB的文件。
有人能指出我的错误在哪里吗?
你应该使用一个循环来复制它,sendfile()可能由于各种原因而不能用一个调用复制所有的数据。 正如janneb指出的那样,sendfile64的返回值是一个ssize_t,所以我们不应该把SSIZE_MAX传递给sendfile,而且sendfile的最后一个参数是size_t,在32位平台上应该是32位。
/* copy file using sendfile */ while (offset < stat_buf.st_size) { size_t count; off64_t remaining = stat_buf.st_size- offset; if (remaining > SSIZE_MAX) count = SSIZE_MAX; else count = remaining; rc = sendfile64 (dest, src, &offset, count); if (rc == 0) { break; } if (rc == -1) { fprintf(stderr, "error from sendfile: %s\n", strerror(errno)); exit(1); } } if (offset != stat_buf.st_size) { fprintf(stderr, "incomplete transfer from sendfile: %lld of %lld bytes\n", rc, (long long)stat_buf.st_size); exit(1); }
请注意,您可以使用off_t,stat,sendfile替换所有64位变体,off64_t,stat64,sendfile64。 只要你有-D_FILE_OFFSET_BITS=64
标志,如果这些类型和函数还不是64位的(比如在32位体系结构上),那么这个定义将会做正确的事情并将off_t转换为off64_t,sendfile到send64等。