AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 436864
Accepted
user9303970
user9303970
Asked: 2018-04-11 13:05:24 +0800 CST2018-04-11 13:05:24 +0800 CST 2018-04-11 13:05:24 +0800 CST

Como um FIFO (pipe nomeado) difere de um tubo regular (pipe sem nome)? [duplicado]

  • 772
Esta pergunta já tem respostas aqui :
Qual é o propósito de usar um FIFO versus um arquivo temporário ou um pipe? (1 resposta)
Quais são as vantagens de usar o pipe nomeado sobre o pipe sem nome? (4 respostas)
Fechado há 4 anos .

Como um FIFO (pipe nomeado) difere de um tubo regular (|)? Pelo que entendi da Wikipedia , ao contrário de um pipe regular, um pipe FIFO "continua vivo" após o término do processo e pode ser excluído algum tempo depois.

Mas se o processo for baseado em um comando shell contendo um pipe ( cat x | grep y), poderíamos "mantê-lo vivo após o processo" se o armazenarmos em uma variável ou arquivo, não é um FIFO?

Além disso, um canal regular também tem o primeiro stdout que obtém, como stdin para outro comando , então também não é uma espécie de canal primeiro a entrar, primeiro a sair?

pipe fifo
  • 2 2 respostas
  • 9733 Views

2 respostas

  • Voted
  1. Best Answer
    derobert
    2018-04-11T15:11:22+08:002018-04-11T15:11:22+08:00

    "Pipe nomeado" é na verdade um nome muito preciso para o que é - é como um pipe normal, exceto que tem um nome (em um sistema de arquivos).

    Um canal — o regular, sem nome ("anônimo") usado em some-command | grep patterné um tipo especial de arquivo. E eu quero dizer arquivo, você lê e escreve nele como faz com qualquer outro arquivo. O Grep realmente não se importa¹ se está lendo de um canal em vez de um terminal³ ou um arquivo comum.

    Tecnicamente, o que acontece nos bastidores é que stdin, stdout e stderr são três arquivos abertos (descritores de arquivo) passados ​​para cada execução de comando. Os descritores de arquivo (que são usados ​​em cada syscall para ler/escrever/etc. arquivos) são apenas números; stdin, stdout e stderr são descritores de arquivo 0, 1 e 2. Portanto, quando seu shell configura, o some-command | grepque ele faz é algo assim:

    1. Pede ao kernel um canal anônimo. Não há nome, então isso não pode ser feito opencomo para um arquivo normal - em vez disso, é feito com pipeou pipe2, que retorna dois descritores de arquivo.⁴

    2. Bifurca um processo filho ( fork()cria uma cópia do processo pai; ambos os lados do pipe estão abertos aqui), copia o lado de gravação do pipe para fd 1 (stdout). O kernel tem um syscall para copiar os números do descritor de arquivo; é dup2()ou dup3(). Em seguida, fecha o lado de leitura e outra cópia do lado de gravação. Finalmente, ele usa execvepara executar some-command. Como o tubo é fd 1, stdout some-commandé o tubo.

    3. Forks de outro processo filho. Desta vez, ele duplica o lado de leitura do pipe para fd 0 (stdin) e executa grep. Portanto, o grep lerá o pipe como stdin.

    4. Em seguida, espera que ambas as crianças saiam.

    5. Nesse ponto, o kernel percebe que o canal não está mais aberto e o lixo o coleta. Isso é o que realmente destrói o tubo.

    Um pipe nomeado apenas dá um nome a esse pipe anônimo, colocando-o no sistema de arquivos. Portanto, agora qualquer processo, em qualquer ponto no futuro, pode obter um descritor de arquivo para o canal usando uma chamada de sistema comum open. Conceitualmente, o canal não será destruído até que todos os leitores/gravadores o fechem e ele seja unlinkremovido do sistema de arquivos.²

    A propósito, é assim que os arquivos em geral funcionam no Unix. unlink(o syscall atrás rmde ) apenas remove um dos nomes do arquivo; somente quando todos os nomes forem removidos e nada tiver o arquivo aberto, ele será realmente excluído. Algumas respostas aqui exploram isso:

    • Por que os hard links parecem ocupar o mesmo espaço que os originais?
    • Como um programa de log pode continuar registrando em um arquivo excluído?
    • O que o Linux está fazendo de diferente que me permite remover/substituir arquivos onde o Windows reclamaria que o arquivo está em uso?

    NOTAS DE RODAPÉ

    1. Tecnicamente, isso provavelmente não é verdade - provavelmente é possível fazer algumas otimizações sabendo, e as implementações reais do grep geralmente foram fortemente otimizadas. Mas conceitualmente isso não importa (e, de fato, uma implementação direta do grep não importaria).
    2. É claro que o kernel não mantém todas as estruturas de dados na memória para sempre, mas as recria, de forma transparente, sempre que o primeiro programa abre o canal nomeado (e então as mantém enquanto estiver aberto). Então é como se eles existissem desde que o nome existe.
    3. O terminal não é um lugar comum para o grep ler, mas é o stdin padrão quando você não especifica outro. Portanto, se você digitar apenas grep patternno seu shell, grepestará lendo no terminal. O único uso para isso que vem à mente é se você estiver prestes a colar algo no terminal.
    4. No Linux, pipes anônimos são criados em um sistema de arquivos especial, pipefs. Consulte Como os pipes funcionam no Linux para obter detalhes. Observe que este é um detalhe de implementação interna do Linux.
    • 23
  2. Peter Cordes
    2018-04-11T16:21:29+08:002018-04-11T16:21:29+08:00

    Acho que você está se confundindo entre a sintaxe do shell para pipelines e a programação subjacente dos sistemas Unix. Um pipe / FIFO é um tipo de arquivo que não é armazenado em disco, mas passa dados de um gravador para um leitor por meio de um buffer no kernel.

    Um pipe/FIFO funciona da mesma forma se o gravador e o leitor se conectaram fazendo chamadas de sistema como open("/path/to/named_pipe", O_WRONLY);, ou com um pipe(2)para criar um novo pipe anônimo e retornar descritores de arquivo aberto para os lados de leitura e gravação.

    fstat(2)no descritor de arquivo de canal fornecerá a você sb.st_mode & S_IFMT == S_IFIFOde qualquer maneira.


    Quando você correfoo | bar :

    • O shell se bifurca como normal para qualquer comando não integrado
    • Em seguida, faz uma pipe(2)chamada de sistema para obter dois descritores de arquivo: a entrada e a saída de um pipe anônimo.
    • Então ele se bifurca novamente .
    • A criança (onde fork()retornou 0)
      • fecha o lado de leitura do pipe (deixando o fd de gravação aberto)
      • e redireciona stdoutpara o fd de gravação comdup2(pipefd[1], 1)
      • então fazexecve("/usr/bin/foo", ...)
    • O pai (onde fork()retornou o PID filho diferente de 0)
      • fecha o lado de escrita do pipe (deixando o read fd aberto)
      • e redireciona stdindo read fd comdup2(pipefd[0], 0)
      • então fazexecve("/usr/bin/bar", ...)

    Você entra em uma situação muito semelhante se correr foo > named_pipe & bar < named_pipe.

    Um pipe nomeado é um ponto de encontro para processos estabelecerem pipes entre si.


    A situação é semelhante a arquivos tmp anônimos versus arquivos com nomes. Você pode open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);criar um arquivo temporário sem nome ( O_TMPFILE), como se tivesse aberto "/path/to/dir/tmpfile"com O_CREATe depois desvinculado, deixando você com um descritor de arquivo para um arquivo excluído.

    Usando linkat, você pode até vincular esse arquivo anônimo ao sistema de arquivos, dando-lhe um nome, se tiver sido criado com O_TMPFILE. ( Você não pode fazer isso no Linux para arquivos que você criou com um nome e depois deletado. )

    • 4

relate perguntas

  • Como canalizar um 'sim' ou 'y' em um programa enquanto é invocado com 'sudo' no bash?

  • Passe o identificador para o pipeline stdin down

  • Como canalizar um comando bash e manter Ctrl + C funcionando?

  • Por que canalizar `mysql` para 'tail' altera o formato de saída?

  • ordem de substituição de processos `te` e `bash`

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve