Неверный аргумент в sendfile () с двумя обычными файлами - PullRequest
3 голосов
/ 31 мая 2010

Я пытаюсь проверить системный вызов sendfile() в Linux 2.6.32, чтобы обнулить данные между двумя обычными файлами. Насколько я понимаю, это должно работать: начиная с 2.6.22, sendfile() был реализован с использованием splice(), и входной файл, и выходной файл могут быть обычными файлами или сокетами.

Ниже приводится содержание sendfile_test.c:

#include <sys/sendfile.h>

#include <fcntl.h>
#include <stdio.h>

int main(int argc, char **argv) {
  int result;
  int in_file;
  int out_file;

  in_file = open(argv[1], O_RDONLY);
  out_file = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);

  result = sendfile(out_file, in_file, NULL, 1);
  if (result == -1)
    perror("sendfile");

  close(in_file);
  close(out_file);

  return 0;
}

А когда я запускаю следующие команды:

$ gcc sendfile_test.c 
$ ./a.out infile outfile

Выход

sendfile: Invalid argument

А при запуске

$ strace ./a.out infile outfile

Выход содержит

open("infile", O_RDONLY)                = 3
open("outfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
sendfile(4, 3, NULL, 1)                 = -1 EINVAL (Invalid argument)

Что я делаю не так?

1 Ответ

6 голосов
/ 31 мая 2010

Вы забыли проверить, что argc равно 3, т.е. вы открываете выходной файл с именем argv[2], но даете своей программе только один аргумент (и вы не проверяете ошибки после open(2) .)

Вы можете использовать strace(1), чтобы узнать, какой системный вызов не удался.

Edit:

Для меня это выглядит как старое ядро. Тот же источник (проверка по модулю ошибок) отлично работает здесь под 2.6.33.4 #3 SMP. Кроме того, по какой-либо конкретной причине вы копируете только один байт?

#include <sys/sendfile.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main( int argc, char *argv[] )
{
    int in_file, out_file;

    if ( argc != 3 )
    {
        fprintf( stderr, "usage: %s <in-file> <out-file>\n", argv[0] );
        exit( 1 );
    }

    if (( in_file = open( argv[1], O_RDONLY )) == -1 ) err( 1, "open" );
    if (( out_file = open( argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644 )) == -1 )
        err( 1, "open(2)" );

    if ( sendfile( out_file, in_file, NULL, 4096 ) == -1 ) err( 1, "sendfile" );

    exit( 0 );
}

Трассировка:

nickf@slack:~/csource/linux/splice$ cc -Wall -pedantic -ggdb -g3 -o sf sndf.c 
nickf@slack:~/csource/linux/splice$ strace ./sf Makefile mm
...
open("Makefile", O_RDONLY)              = 3
open("mm", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
sendfile(4, 3, NULL, 4096)              = 239
exit_group(0)                           = ?
nickf@slack:~/csource/linux/splice$ diff Makefile mm 
nickf@slack:~/csource/linux/splice$
...