Será emenda do Linux (2) funciona quando splicing de um soquete TCP?

votos
9

Eu tenho escrito um pequeno programa para se divertir que transfere arquivos sobre TCP em C no Linux. O programa lê um arquivo de um soquete e grava-lo para o arquivo (ou vice-versa). Eu originalmente usado leitura / gravação eo programa funcionou corretamente, mas depois que eu aprendi sobre emenda e queria dar-lhe uma tentativa.

O código que eu escrevi com emenda funciona perfeitamente ao ler de stdin (arquivo redirecionado) e escrita para o soquete TCP, mas não imediatamente com emenda definir errno para EINVAL quando a leitura da tomada e escrever para stdout. A página man afirma que EINVAL é definido quando nem descritor é um tubo (não é o caso), um deslocamento é passado para um fluxo que não pode buscar (sem compensações passado), ou o sistema de arquivos não suporta splicing, o que me leva a minha pergunta: isso significa que o TCP pode emendar a partir de um tubo, mas não para ?

Estou incluindo o código abaixo (código de manipulação de erro de menos) na esperança de que eu acabei de fazer algo errado. É baseado fortemente no exemplo Wikipedia para emenda .

static void splice_all(int from, int to, long long bytes)
{
    long long bytes_remaining;
    long result;

    bytes_remaining = bytes;
    while (bytes_remaining > 0) {
        result = splice(
            from, NULL,
            to, NULL,
            bytes_remaining,
            SPLICE_F_MOVE | SPLICE_F_MORE
        );

        if (result == -1)
            die(splice_all: splice);

        bytes_remaining -= result;
    }
}

static void transfer(int from, int to, long long bytes)
{
    int result;
    int pipes[2];

    result = pipe(pipes);

    if (result == -1)
        die(transfer: pipe);

    splice_all(from, pipes[1], bytes);
    splice_all(pipes[0], to, bytes);

    close(from);
    close(pipes[1]);
    close(pipes[0]);
    close(to);
}

Em uma nota lateral, eu acho que o acima irá bloquear no primeiro splice_allquando o arquivo é grande o suficiente devido ao tubo de encher (?), Então eu também tenho uma versão do código que forké para ler e escrever a partir do tubo de ao mesmo tempo, mas tem o mesmo erro que esta versão e é mais difícil de ler.

EDIT: Minha versão do kernel é 2.6.22.18-co-0.7.3 (executando coLinux no XP.)

Publicado 19/05/2009 em 21:48
fonte usuário
Em outras línguas...                            


2 respostas

votos
8

Qual versão do kernel é isso? Linux tem tido apoio para a emenda de um soquete TCP desde 2.6.25 (cometer 9c55e01c0 ), então se você estiver usando uma versão anterior, você está sem sorte.

Respondeu 19/05/2009 em 21:58
fonte usuário

votos
2

Você precisa da cada vez que você faz uma única emenda de a (o é para a quantidade de bytes apenas lido pelo último single emenda). Motivo: tubos representa um buffer de memória do kernel finito. Então, se bytes é mais do que isso, você vai bloquear para sempre na sua .splice_allpipes[0]tofrompipes[1]splice_allsplice_all(from, pipes[1], bytes)

Respondeu 28/12/2010 em 01:24
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more