copy_file_range(2) - wariua/manpages-ko GitHub Wiki
copy_file_range - ํ ํ์ผ์์ ๋ค๋ฅธ ํ์ผ๋ก ๋ฐ์ดํฐ ๊ตฌ๊ฐ ๋ณต์ฌํ๊ธฐ
#include _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()
์์คํ
ํธ์ถ์ ์ปค๋์์ ์ฌ์ฉ์ ๊ณต๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๊ณ ๋ฐ๋ ์ถ๊ฐ ๋น์ฉ ์์ด ์ปค๋ ๋ด์์ ๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ ๊ฐ์ ๋ณต์ฌ๋ฅผ ์ํํ๋ค. ํ์ผ ๋์คํฌ๋ฆฝํฐ fd_in
์์ ํ์ผ ๋์คํฌ๋ฆฝํฐ fd_out
์ผ๋ก ์ต๋ len
๋ฐ์ดํธ๊น์ง ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๋ฉฐ, ๋์ ํ์ผ์์ ์์ฒญ ๋ฒ์ ๋ด์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ฉด ๋ฎ์ด ์ด๋ค.
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
์ด ๊ฐ๋ฆฌํค๋ ์ด๋ฆฐ ํ์ผ ๊ธฐ์ ํญ๋ชฉ(open(2) ์ฐธ๊ณ )์O_APPEND
ํ๋๊ทธ๊ฐ ์ค์ ๋์ด ์๋ค. EFBIG
- ๊ตฌํ์์ ์ ์ํ๋ ํ์ผ ์ต๋ ํฌ๊ธฐ๋ ํ๋ก์ธ์ค์ ํ์ผ ํฌ๊ธฐ ์ ํ์ ์ด๊ณผํ๋๋ก ํ์ผ ์ฐ๊ธฐ ์๋๊ฐ ์ด๋ค์ก๊ฑฐ๋, ๊ฐ๋ฅํ ์ต๋ ์คํ์ ์ ๋๋ ์์น์์ ์ฐ๊ธฐ ์๋๊ฐ ์ด๋ค์ก๋ค.
EINVAL
- ์์ฒญ ๋ฒ์๊ฐ ์ถ๋ฐ ํ์ผ์ ๋์ ๋ฒ์ด๋๋ค. ๋๋
flags
์ธ์๊ฐ 0์ด ์๋๋ค. EIO
- ๋ณต์ฌ ์ค์ ์ ์์ค I/O ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
EISDIR
-
fd_in
์ด๋fd_out
์ด ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ค. ENOMEM
- ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ.
ENOSPC
- ๋์ ํ์ผ ์์คํ ์ ๋ณต์ฌ๋ฅผ ์๋ฃํ๊ธฐ ์ํ ์ถฉ๋ถํ ๊ณต๊ฐ์ด ์๋ค.
EXDEV
-
file_in
๊ณผfile_out
์ด ๊ฐ๋ฆฌํค๋ ํ์ผ์ด ๊ฐ์ ํ์ผ ์์คํ ์์ ์์ง ์๋ค.
๋ฆฌ๋
์ค 4.5์์ copy_file_range()
์์คํ
ํธ์ถ์ด ์ฒ์ ๋ฑ์ฅํ๋ค. glibc 2.27์์๋ ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์์ ๊ฒฝ์ฐ ์ฌ์ฉ์ ๊ณต๊ฐ ์๋ฎฌ๋ ์ด์
์ ์ ๊ณตํ๋ค.
copy_file_range()
์์คํ
ํธ์ถ์ ๋นํ์ค ๋ฆฌ๋
์ค ๋ฐ GNU ํ์ฅ์ด๋ค.
file_in
์ด ํฌ์ ํ์ผ์ด๋ฉด ์์ฒญ ๋ฒ์ ๋ด์ ์กด์ฌํ๋ ๊ตฌ๋ฉ์ copy_file_range()
๊ฐ ์ฑ์ ๋ฒ๋ฆด ์ ์๋ค. ๋ฃจํ ์์์ copy_file_range()
๋ฅผ ํธ์ถํ๋ฉด์ lseek(2) SEEK_DATA
๋ฐ SEEK_HOLE
๋์์ผ๋ก ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ์ ์์น๋ฅผ ์์๋ด๋ ๋ฐฉ์์ด ์ข์ ์ ์๋ค.
copy_file_range()
๋ ํ์ผ ์์คํ
์์ reflink(์ฆ ์ฌ๋ฌ ์์ด๋
ธ๋๊ฐ ๋์ผ copy-on-write ๋์คํฌ ๋ธ๋ก์ ๋ํ ํฌ์ธํฐ ๊ณต์ )๋ ์๋ฒ ์ธก ๋ณต์ฌ(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 ์ ๋ฒ์ ์์๋ syscall(2)๋ก copy_file_range()๋ฅผ
ํธ์ถํด์ผ ํ๋ค. */
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, "Usage: %s <source> <destination>\n", argv[0]);
exit(EXIT_FAILURE);
}
fd_in = open(argv[1], O_RDONLY);
if (fd_in == -1) {
perror("open (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("open (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);
}
lseek(2), sendfile(2), splice(2)
2019-03-06