노틸러스는 파일을 붙여넣을 때 쓰기 시스템 호출을 호출하지 않습니다.

노틸러스는 파일을 붙여넣을 때 쓰기 시스템 호출을 호출하지 않습니다.

Ubuntu 14.04 데스크톱 버전에서 Linux 커널 모듈을 사용하여 일부 시스템 호출을 연결하려고 합니다.

그런데 훅 write(unsigned int fd, const char __user *buf, size_t count)하고 filename으로 돌려 보니 노틸러스 에 복사해서 붙여넣을 fd때 이 폴더에 write가 호출되지 않는 것을 발견했습니다 . 그러나 을 사용하면 가 호출되고 파일 이름이 정확히 ./home/user/1.txt/home/user/folder/cp /home/user/1.txt /home/user/folderwrite/home/user/folder/1.txt

후크도 시도했지만 pwrite노틸러스를 사용하여 파일을 붙여넣을 때 여전히 호출이 감지되지 않습니다.

write그렇다면 대상이 시스템 호출을 호출하지 않을 때 노틸러스는 어떻게 파일을 특정 폴더에 복사하여 붙여넣을까요?

답변1

노틸러스는 최적화 목적으로 다른 접근 방식을 사용하는 것 같습니다.

/ntest/testfile내부에 45바이트의 테스트 파일이 있다고 가정해 보겠습니다.

Lorem ipsum dolor sit amet
Leroooy Jeeenkins

디렉토리로 옮기고 싶습니다 /ntest2. Nautilus가 정확히 무엇을 하고 있는지 추적하려면 다음과 같이 시작할 수 있습니다(실제로는 덜 엄격한 제한으로 여러 번 실행했지만 좋은 시작입니다).

strace -f -P '/ntest/testfile' -P '/ntest2/testfile' -qq nautilus

기본적으로 다음 발췌 내용은 무슨 일이 일어나고 있는지 설명합니다( pipe2()위 명령은 호출을 캡처하지 않습니다. 다른 추적 세션을 기반으로 삽입했습니다).

openat(AT_FDCWD, "/ntest/testfile", O_RDONLY) = 35
openat(AT_FDCWD, "/ntest2/testfile", O_WRONLY|O_CREAT|O_EXCL, 0644) = 36
pipe2([37, 38], O_CLOEXEC)  = 0
stat("/ntest2/testfile", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
splice(35, [0], 38, NULL, 1048576, SPLICE_F_MORE) = 45
splice(37, NULL, 36, [0], 45, SPLICE_F_MORE) = 45
close(35)                   = 0
close(36)                   = 0

커널과 사용자 공간 간에 데이터를 복사할 필요 없이 s 간에 일부 데이터를 전송할 수 splice(2)있도록 Nautilus에서 사용됩니다 . 한쪽 끝에 파이프가 필요하기 fd때문에 노틸러스는 입력 파일 설명자와 출력 파일 설명자가 있는 파이프를 생성합니다 . 소스 및 대상 파일을 열고 파이프를 생성한 후 노틸러스는 소스 파일의 데이터를 파이프의 입력으로 읽는 데 사용되며, 두 번째는 파이프의 데이터를 출력 파일에 쓰는 데 사용됩니다. 이 방법은 일반적인 방법처럼 커널에서 사용자로, 사용자에서 커널로의 데이터 변환을 포함하지 않습니다 .man 2 splice3837splice()splice()read()write()

이 동작은 Nautilus에만 국한된 것이 아니라 Nautilus가 사용하는 라이브러리(glib)에만 해당됩니다. 처럼 보인다이것은 splice() 호출입니다.Nautilus가 glib를 사용하는 것을 관찰했습니다.g_file_copy()이는 차례로 호출됩니다.file_copy_fallback()->splice_stream_with_progress()->do_splice().

관련 정보