7

splice() に関する別の質問があります。私はそれを使用してファイルをコピーしたいと考えており、splice の Wikipedia ページの例のように、パイプで結合された 2 つの splice 呼び出しを使用しようとしています。あるファイルから最初の 32K バイトを読み取り、別のファイルに書き込むだけの簡単なテスト ケースを作成しました。

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main(int argc, char **argv) {
    int pipefd[2];
    int result;
    FILE *in_file;
    FILE *out_file;

    result = pipe(pipefd);

    in_file = fopen(argv[1], "rb");
    out_file = fopen(argv[2], "wb");

    result = splice(fileno(in_file), 0, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE);
    printf("%d\n", result);

    result = splice(pipefd[0], NULL, fileno(out_file), 0, 32768, SPLICE_F_MORE | SPLICE_F_MOVE);
    printf("%d\n", result);

    if (result == -1)
        printf("%d - %s\n", errno, strerror(errno));

    close(pipefd[0]);
    close(pipefd[1]);
    fclose(in_file);
    fclose(out_file);

    return 0;
}

これを実行すると、入力ファイルは正しく読み込まれているように見えますが、2 番目の splice 呼び出しは EINVAL で失敗します。ここで私が間違っていることを知っている人はいますか?

ありがとう!

4

3 に答える 3

4

スプライスのマンページから:

   EINVAL Target  file  system  doesn't  support  splicing; target file is
          opened in append mode; neither of the descriptors  refers  to  a
          pipe; or offset given for non-seekable device.

記述子の 1 つがパイプであり、ファイルが追加モードで開かれていないことがわかっています。また、オフセットが指定されていないこともわかっているため (0NULL- ゼロ オフセットへのポインターを渡すことを意味していましたか?)、それは問題ではありません。したがって、使用しているファイル システムは、ファイルへのスプライシングをサポートしていません。

于 2009-10-17T01:10:22.080 に答える
3

どのような種類のファイル システムとの間でコピーしていますか?

あなたの例は、両方のファイルが ext3 にある場合に私のシステムで実行されますが、外部ドライブを使用すると失敗します (DOS または NTFS の場合は忘れてしまいます)。私の推測では、ファイルの 1 つまたは両方が、splice がサポートしていないファイル システム上にあると思われます。

于 2009-10-17T01:33:28.733 に答える
2

splice(2)システムコールは、ファイル間ではなくファイルとパイプ間のコピー用であるため、他の回答で指摘されているように、ファイル間のコピーには使用できません。

ただし、Linux 4.5 以降では、ファイル間でコピーできる新しいcopy_file_range(2)システム コールが利用可能です。NFS の場合、サーバー側のコピーが発生することさえあります。

リンクされた man ページには、完全なサンプル プログラムが含まれています。

于 2016-08-09T02:37:21.320 に答える