Tamanho do buffer do kernel do pipe anônimo

1

Estou tentando entender as estruturas associadas a uma chamada para o syscall de pipe.

int pipe(int pipefd[2]);

Pelo que entendi, haverá um buffer / estrutura de kernel de "leitura" e "gravação" associado ao final de leitura pipefd[0] e gravação final pipefd[1] do canal.

Eu realmente gostaria de alguns ponteiros (sem trocadilhos) em estruturas referentes às extremidades de leitura / gravação deste pipe, que acredito serem apenas descritores de arquivos. Por exemplo, como o computador sabe que não há mais bytes a serem transferidos "lidos" durante uma operação de leitura, como:

char tmpBuff[15];
bytesRead = read(filedes[0], tmpBuff, 15);

Qual estrutura é definida para acompanhar o buffer, a posição do arquivo, etc. associada aos descritores filedes[0] ou filedes[1] ?

De acordo com a página man do ssize_t read(int fd, void *buf, size_t count);

READ(2) Linux Programmer's Manual

NAME read - read from a file descriptor

SYNOPSIS #include

   ssize_t read(int fd, void *buf, size_t count);

RETURN VALUE On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number.

Deve haver algum tipo de estrutura apontada como o índice referido por um descritor de arquivo para compor algum tipo de estrutura como abaixo.

struct file_info
{
    char *start_buf;
    char *end_buf;
    int fileposition;    
};

Por fim, é possível do userspace acessar esses valores por curiosidade e criar um programa que diga algo como "ler o descritor de arquivos foo, há 120 bytes no buffer e a posição do arquivo está em 0 ". Como o buffer não está acessível no nível do usuário (eu acho), como poderíamos acessar essas informações, apenas conhecendo o valor do descritor de arquivo?

    
por John 07.02.2017 / 23:29

1 resposta

1

Primeiro, algumas de suas perguntas podem ser respondidas aqui: Qual é o tamanho do buffer de tubos?

Um pipe é um buffer circular limitado que é mantido pelo kernel. A chamada de sistema pipe cria um novo canal e associa dois descritores de arquivo ao pipe, um para gravar no pipe e outro para leitura do pipe.

Grava no pipe, através do descritor de arquivo associado, copiar os dados fornecidos para aquele buffer, se houver espaço para isso. Se não houver espaço para os dados, a chamada para write () bloqueará o aplicativo de chamada até que o espaço se torne disponível. Se um processo é bloqueado em uma operação write () em um pipe e algum outro processo / thread lê dados suficientes do pipe que permitiriam ao writer bloqueado completar sua escrita, então o writer bloqueado é acordado e permitido prosseguir. / p>

O processo funciona de forma semelhante para os leitores. Se um processo de leitura tentar ler de um pipe e não houver nada para ler, a chamada do sistema read () ficará bloqueada esperando que os dados se tornem disponíveis. Se um processo for bloqueado em uma operação read () em um papa e algum outro processo / thread gravar dados no canal que permitirão que o leitor bloqueado conclua sua leitura, o leitor bloqueado será ativado e poderá continuar.

Em termos do tamanho de um pipe, você pode encontrar algumas informações na seguinte entrada de manual man de man 7 pipe :

Pipe capacity

   A pipe has a limited capacity.  If the pipe is full, then a write(2)
   will block or fail, depending on whether the O_NONBLOCK flag is set
   (see below).  Different implementations have different limits for the
   pipe capacity.  Applications should not rely on a particular
   capacity: an application should be designed so that a reading process
   consumes data as soon as it is available, so that a writing process
   does not remain blocked.

   In Linux versions before 2.6.11, the capacity of a pipe was the same
   as the system page size (e.g., 4096 bytes on i386).  Since Linux
   2.6.11, the pipe capacity is 65536 bytes.  Since Linux 2.6.35, the
   default pipe capacity is 65536 bytes, but the capacity can be queried
   and set using the fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ operations.
   See fcntl(2) for more information.

Veja um exemplo de programa para consultar o tamanho do pipe:

#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    int pipefds[2] = { -1, -1 };

    assert(pipe(pipefds) == 0);

    printf("pipe size: %d\n", fcntl(pipefds[0], F_GETPIPE_SZ));

    // pipe will be closed on exit
    return EXIT_SUCCESS;
}

A execução do programa me dá:

$ ./a.out
pipe size: 65536
    
por 08.02.2017 / 05:17