Parece que o Nautilus usa uma abordagem diferente para fins de otimização.
Digamos que eu tenha um arquivo de teste /ntest/testfile com 45 bytes dentro:
Lorem ipsum dolor sit amet
Leroooy Jeeenkins
Eu quero movê-lo para o diretório /ntest2 . Para rastrear o que exatamente o Nautilus faz, posso ativá-lo assim (na verdade, fiz vários lançamentos com limitações menos rigorosas, mas isso é um bom começo):
strace -f -P '/ntest/testfile' -P '/ntest2/testfile' -qq nautilus
Essencialmente, o trecho a seguir explica o que acontece (note que pipe2() call não é capturado pelo comando acima - eu o inseri baseado em outras sessões de rastreamento):
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
O Nautilus usa splice(2) , que permite transferir alguns dados entre fd s sem copiá-los entre o kernel e os espaços do usuário. Como man 2 splice requer que uma das extremidades seja um canal, o Nautilus cria um canal com descritor de arquivo de entrada 38 e descritor de arquivo de saída 37 . Após abrir os arquivos de origem e de destino e criar o canal, o Nautilus usa splice() para ler dados do arquivo de origem para a entrada do pipe; então o segundo splice() é usado para gravar dados desse pipe no arquivo de saída. Essa abordagem não envolve transições de dados de kernel para usuário e de usuário para kernel, como seria com a abordagem comum de read() - write() .
Note que este comportamento não é específico do Nautilus, mas sim da biblioteca que ele usa (glib). Parece que esta é a chamada splice () que observamos, como o Nautilus usa g_file_copy () da glib que, por sua vez, chama file_copy_fallback () - > splice_stream_with_progress () - > do_splice () .