ИМЯ copy_file_range - копирует часть данных из одного файла в другой
ОБЗОР #include <sys/syscall.h> #include <unistd.h>
ssize_t copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
ОПИСАНИЕ Системный вызов copy_file_range() выполняет внутриядерное копирование между двумя файловыми дескрипторами без дополнительных накладных расходов по передаче данных из ядра в пользовательское пространство и затем обратно в ядро. Он копирует до len байт данных из файлового дескриптора fd_in в файловый дескриптор fd_out, перезаписывая существующие данные внутри запрашиваемой области файла назначения.
Следующая семантика применяется к off_in и подобная ей к off_out:
* Если off_in равно NULL, то байты читаются из fd_in начиная с файлового смещения, а файловое смещение корректируется на количество скопированных байт.
* Если off_in не равно NULL, то off_in должно указывать на буфер, задающий начальное смещение в fd_in, из которого будут читаться байты. Файловое смещение fd_in не изменяется, но off_in изменяется соответствующим образом.
Аргумент flags предназначен для будущих расширений, а пока его значение должно быть равно 0.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ При успешном выполнении copy_file_range() возвращает количество скопированных между файлами байт. Оно может быть меньше запрашиваемой длины.
В случае ошибки copy_file_range() возвращает -1, а errno устанавливается в соответствующее значение.
ОШИБКИ EBADF Один или оба файловых дескрипторов некорректны; или fd_in не открыт на чтение; или fd_out не открыт на запись; или для открытого файлового описания, на которое ссылается fd_out, установлен флаг O_APPEND.
EINVAL Запрашиваемая область выходит за конец файла-источника; или аргумент flags не равен 0.
EIO Во время копирования возникла низкоуровневая ошибка ввода-вывода.
ENOMEM Не хватает памяти.
ENOSPC Недостаточно места на файловой системе назначения для завершения копирования.
EXDEV Файлы, на которые ссылаются file_in и file_out, находятся на разным смонтированных файловых системах.
ВЕРСИИ Системный вызов copy_file_range() впервые появился в Linux 4.5.
Вызов copy_file_range() даёт файловым системам возможность реализовать «ускорение копирования», например, использовать ссылочные связи (reflinks, т. е., две или более инод, использующих общие указатели для одного копирования-при-записи дисковых блоков) или копирование-на-сервере (server-side-copy, в случае использования NFS).
ПРИМЕР #define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/syscall.h> #include <unistd.h>
static loff_t copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) { return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags); }
int main(int argc, char **argv) { int fd_in, fd_out; struct stat stat; loff_t len, ret;
if (argc != 3) { fprintf(stderr, "Использование: %s <источник> <приёмник>\n", argv[0]); exit(EXIT_FAILURE); }
fd_in = open(argv[1], O_RDONLY); if (fd_in == -1) { perror("открытие (argv[1])"); exit(EXIT_FAILURE); }
if (fstat(fd_in, &stat) == -1) { perror("fstat"); exit(EXIT_FAILURE); }
len = stat.st_size;
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd_out == -1) { perror("открытие (argv[2])"); exit(EXIT_FAILURE); }
do { ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
close(fd_out); exit(EXIT_SUCCESS); }
СМОТРИТЕ ТАКЖЕ lseek(2), sendfile(2), splice(2)
|