COPY_FILE_RANGE(2) | Руководство программиста Linux | COPY_FILE_RANGE(2) |
ИМЯ¶
copy_file_range - копирует часть данных из одного файла в другой
СИНТАКСИС¶
#define _GNU_SOURCE #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);
ОПИСАНИЕ¶
The copy_file_range() system call performs an in-kernel copy between two file descriptors without the additional cost of transferring data from the kernel to user space and then back into the kernel. It copies up to len bytes of data from file descriptor fd_in to file descriptor fd_out, overwriting any data that exists within the requested range of the target file.
Следующая семантика применяется к 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
- One or more file descriptors are not valid; or fd_in is not open for reading; or fd_out is not open for writing; or the O_APPEND flag is set for the open file description referred to by fd_out.
- EFBIG
- Попытка записать в файл, который превышает заданное при реализации ограничение на размер файла или ограничение на размер файла для текущего процесса, или запись в позицию после максимально разрешённого смещения.
- EINVAL
- Requested range extends beyond the end of the source file; or the flags argument is not 0.
- EIO
- Во время копирования возникла низкоуровневая ошибка ввода-вывода.
- EISDIR
- fd_in or fd_out refers to a directory.
- ENOMEM
- Не хватает памяти.
- ENOSPC
- Недостаточно места на файловой системе назначения для завершения копирования.
- EXDEV
- Файлы, на которые ссылаются file_in и file_out, находятся не в одной смонтированной файловой системе.
ВЕРСИИ¶
Системный вызов copy_file_range() впервые появился в Linux 4.5, но если он недоступен, в glibc 2.27 предоставляется эмуляция в пользовательском пространстве.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
Системный вызов copy_file_range() является нестандартным расширением Linux и GNU.
ЗАМЕЧАНИЯ¶
Если файл file_in является разреженным (sparse), то copy_file_range() может расширить дыры, существующие в запрашиваемой области. Пользователи могут получить преимущество от вызова copy_file_range() в цикле, и используя операции lseek(2) SEEK_DATA и SEEK_HOLE для поиска расположений сегментов данных.
Вызов copy_file_range() даёт файловым системам возможность реализовать «ускорение копирования», например, использовать ссылочные связи (т. е., две или более инод, использующих общие указатели для одного копирования-при-записи дисковых блоков) или копирование-на-сервере (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> / * В версиях glibc до 2.27, мы должны ссылаться на copy_file_range ()
используя syscall(2) * / 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);
if (ret == -1) {
perror("copy_file_range");
exit(EXIT_FAILURE);
}
len -= ret;
} while (len > 0);
close(fd_in);
close(fd_out);
exit(EXIT_SUCCESS); }
СМ. ТАКЖЕ¶
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 4.16. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.
ПЕРЕВОД¶
Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Katrin Kutepova <blackkatelv@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
2 февраля 2018 г. | Linux |