- bullseye-backports 4.18.1-1~bpo11+1
- testing 4.18.1-1
- unstable 4.18.1-1
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);
ОПИСАНИЕ¶
Системный вызов 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 изменяется соответствующим образом.
Значения fd_in и fd_out могут ссылаться на один и тот же файл. Если это так, то диапазонам источника и приёмника нельзя перекрываться.
Аргумент flags предназначен для будущих расширений, а пока его значение должно быть равно 0.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении copy_file_range() возвращает количество скопированных между файлами байт. Оно может быть меньше запрашиваемой длины. Если файловое смещение fd_in в конце или за концом файла, то байты не копирются и copy_file_range() возвращает ноль.
В случае ошибки copy_file_range() возвращает -1, а errno устанавливается в соответствующее значение.
ОШИБКИ¶
- EBADF
- Один или оба файловых дескриптора недействительны.
- EBADF
- Дескриптор fd_in не открыт на чтение или дескриптор fd_out не открыт на запись.
- EBADF
- В открытом файловом описании, на которое ссылается файловый дескриптор fd_out, установлен флаг O_APPEND (смотрите open(2)).
- EFBIG
- Попытка записать в позицию вне максимально поддерживаемого ядром файлового смещения.
- EFBIG
- Попытка записи диапазона, который превышает разрешённый максимальный размер файла. Максимальный размер файла различается в реализациях файловых систем и может отличаться от разрешённого максимального файлового смещения.
- EFBIG
- Попытка записи, выходящее за ограничение ресурса процесса на размер файла. Также это может вызвать получение процессом сигнала SIGXFSZ.
- EINVAL
- Аргумент flags не равен 0.
- EINVAL
- Значения fd_in и fd_out ссылаются на один и тот же файл и диапазоны источника и приёмника перекрываются.
- EINVAL
- Значение fd_in или fd_out указывает на необычный файл.
- EIO
- Во время копирования возникла низкоуровневая ошибка ввода-вывода.
- EISDIR
- Значение fd_in или fd_out указывает на каталог.
- ENOMEM
- Не хватает памяти.
- ENOSPC
- Недостаточно места на файловой системе назначения для завершения копирования.
- EOVERFLOW
- Запрошенный диапазон источника и приёмника слишком большой для представления в указанном типе данных.
- EPERM
- Значение fd_out ссылается на файл с постоянными данными (immutable).
- ETXTBSY
- Значение fd_in или fd_out указывает на активный файл подкачки.
- EXDEV
- Файлы, на которые ссылаются fd_in и fd_out, находятся не в одной смонтированной файловой системе (до Linux 5.3).
ВЕРСИИ¶
Системный вызов copy_file_range() впервые появился в Linux 4.5, но если он недоступен, в glibc 2.27 предоставляется эмуляция в пользовательском пространстве.
В ядре версии 5.3 произошли значительные перемены. Уточнены области API, которые были нечётно определены, и границы API теперь строже проверяются, по сравнению с ранними ядрами. Приложения должны следовать поведению и требованиям ядер 5.3.
В Linux 5.3 появилась поддержка копирования между файловыми системами. В старых ядрах при попытках копирования между файловыми системами возвращается ошибка -EXDEV.
СООТВЕТСТВИЕ СТАНДАРТАМ¶
Системный вызов copy_file_range() является нестандартным расширением Linux и GNU.
ЗАМЕЧАНИЯ¶
Если файл fd_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 && ret > 0);
close(fd_in);
close(fd_out);
exit(EXIT_SUCCESS); }
СМ. ТАКЖЕ¶
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу 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.
9 июня 2020 г. | Linux |