Jam*_*ell 12 c linux file-io mmap copy
我想通过在Linux中使用内存映射I/O来尝试将文件的内容复制到另一个文件mmap()
.目的是自己检查一下这是否比使用更好fread()
,fwrite()
以及它如何处理大文件(例如,像几个GiB,因为文件被读取整个我想知道如果我需要有这么多的内存量).
这是我正在使用的代码:
// Open original file descriptor:
int orig_fd = open(argv[1], O_RDONLY);
// Check if it was really opened:
if (orig_fd == -1) {
fprintf(stderr, "ERROR: File %s couldn't be opened:\n", argv[1]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
exit(EX_NOINPUT);
}
// Idem for the destination file:
int dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
// Check if it was really opened:
if (dest_fd == -1) {
fprintf(stderr, "ERROR: File %s couldn't be opened:\n", argv[2]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
// Close original file descriptor too:
close(orig_fd);
exit(EX_CANTCREAT);
}
// Acquire file size:
struct stat info = {0};
if (fstat(orig_fd, &info)) {
fprintf(stderr, "ERROR: Couldn't get info on %s:\n", argv[1]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
// Close file descriptors:
close(orig_fd);
close(dest_fd);
exit(EX_IOERR);
}
// Set destination file size:
if (ftruncate(dest_fd, info.st_size)) {
fprintf(stderr, "ERROR: Unable to set %s file size:\n", argv[2]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
// Close file descriptors:
close(orig_fd);
close(dest_fd);
exit(EX_IOERR);
}
// Map original file and close its descriptor:
char *orig = mmap(NULL, info.st_size, PROT_READ, MAP_PRIVATE, orig_fd, 0);
if (orig == MAP_FAILED) {
fprintf(stderr, "ERROR: Mapping of %s failed:\n", argv[1]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
// Close file descriptors:
close(orig_fd);
close(dest_fd);
exit(EX_IOERR);
}
close(orig_fd);
// Map destination file and close its descriptor:
char *dest = mmap(NULL, info.st_size, PROT_WRITE, MAP_SHARED, dest_fd, 0);
if (dest == MAP_FAILED) {
fprintf(stderr, "ERROR: Mapping of %s failed:\n", argv[2]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
// Close file descriptors and unmap first file:
munmap(orig, info.st_size);
close(dest_fd);
exit(EX_IOERR);
}
close(dest_fd);
// Copy file contents:
int i = info.st_size;
char *read_ptr = orig, *write_ptr = dest;
while (--i) {
*write_ptr++ = *read_ptr++;
}
// Unmap files:
munmap(orig, info.st_size);
munmap(dest, info.st_size);
Run Code Online (Sandbox Code Playgroud)
我认为它可能是一种方法,但我一直在尝试映射目标文件时出错,具体来说是代码13(权限被拒绝).
我不知道为什么它会失败,我可以写入该文件,因为文件被创建,所有和我正在尝试复制的文件只是几个KiB的大小.
有人能发现问题吗?为什么我有权映射原始文件而不是目标文件?
注意:如果有人要使用循环来复制问题中发布的字节而不是memcpy
例如,则循环条件应该是i--
复制所有内容.感谢jxh发现它.
jxh*_*jxh 14
从mmap()
手册页:
EACCES
文件描述符是指非常规文件.或者请求了MAP_PRIVATE,但fd未打开以供阅读.或者请求了MAP_SHARED并且设置了PROT_WRITE,但是在读/写(O_RDWR)模式下fd未打开.或者设置了PROT_WRITE,但该文件仅附加.
您正在打开目标文件O_WRONLY
.请O_RDWR
改用.
此外,您应该使用memcpy
复制内存而不是使用自己的循环:
memcpy(dest, orig, info.st_size);
Run Code Online (Sandbox Code Playgroud)
你的循环有1个错误.