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 / 564029
Accepted
TheMeaningfulEngineer
TheMeaningfulEngineer
Asked: 2020-01-26 03:32:27 +0800 CST2020-01-26 03:32:27 +0800 CST 2020-01-26 03:32:27 +0800 CST

O que é responsável por conectar /dev/pts/10 com stdout/stdin/stderr?

  • 772

Ao executar um comando em ttyum terminal, ele retorna /dev/pts/10.

Além disso, existem os arquivos /dev/stdout /dev/stdine /dev/stderr. Interagir com eles diretamente mostra os resultados no terminal.

user@laptop:build$ tty
/dev/pts/10
user@laptop:build$ echo "Test" > /dev/stdout
Test
user@laptop:build$ echo "Test" > /dev/stdin
Test
user@laptop:build$ echo "Test" > /dev/stderr
Test

Além disso, qualquer aplicativo cli, iniciado a partir do shell, terá os descritores de arquivo abertos para stdout/ stderr/ stdin. ou seja, se você executar um script que imprime algo, imprimir é equivalente a escrever em stdout.

Até agora stdout// foram as únicas interfaces com as quais o shell trabalha stderr. stdinIsso também vale para os aplicativos.

Algum componente do sistema operacional está eventualmente movendo os dados gravados stdoutno terminal, caso contrário, eu não veria nada impresso.

Quando e onde uma conexão entre stdout/stdin/stderre o terminal acontece para que a interação com std*realmente resulte em algo no terminal?

Minha suposição aproximada que eu gostaria de ter desafiado é:

/dev/stdout, /dev/stdine /dev/stderrsão criados pelo shell em execução, eles não existem sem um shell.

O shell configura o canal de comunicação com o arquivo de dispositivo real que representa o terminal ( /dev/pts/10) e expõe as funcionalidades do terminal por meio /dev/stdoutde , /dev/stdine /dev/stderr. Dessa forma, o shell fornece aos aplicativos uma interface de arquivo simples, em vez de todos os aplicativos se preocuparem em como trabalhar o arquivo do dispositivo para impressão simples.

Atualizar

Apesar /dev/pts/10de ser um pseudoterminal, darei mais valor às respostas que conseguirem dar a resposta sem introduzir o conceito de pseudoterminal. Estou vindo de uma perspectiva que apenas distrairá a resposta à pergunta:

Quando e onde uma conexão entre stdout/stdin/stderre o terminal acontece para que a interação com /dev/std*realmente resulte em algo no terminal?

linux shell
  • 3 3 respostas
  • 1848 Views

3 respostas

  • Voted
  1. Piotr P. Karwasz
    2020-01-26T12:20:54+08:002020-01-26T12:20:54+08:00

    /dev/pts/10é a extremidade escrava de um par de dispositivos pseudoterminais . Na outra ponta está o programa que abriu o dispositivo clone mestre /dev/ptmxe recebeu /dev/pts/10como par (cada vez que você abre /dev/ptmx, obtém um escravo diferente). A conexão entre /dev/ptmxe /dev/pts/10é basicamente um tubo bidirecional com uma torção .

    Ao abrir um aplicativo emulador de terminal:

    • ele abre /dev/ptmxe obtém o nome da outra extremidade. Configura a outra extremidade e a abre,
    • ele bifurca,
    • o novo processo abre a outra extremidade do dispositivo pseudoterminal e conecta seu stdin , stdout e stderr a ele,
    • o novo processo executa o shell.

    O shell não faz nada para configurar esses três descritores de arquivo, ele os herda de seu processo pai. Da mesma forma que seus filhos herdarão os descritores de arquivo do shell.

    Observação : Em um sistema Linux /dev/stdin, /dev/stdoute /dev/stderrsão arquivos reais, que por uma série de links simbólicos apontam para /proc/<pid>/0, /proc/<pid>/1e /proc/<pid>/2, que por sua vez apontam para o dispositivo de entrada/saída real: no seu caso /dev/pts/10.

    A existência desses três fluxos padrão é garantida pela biblioteca C.

    Edit : para resolver sua pergunta atualizada, vamos esclarecer alguns pontos da resposta:

    • tudo escrito /proc/pts/*é lido pelo terminal que o criou e exibido, tudo lido /proc/pts/*vem de um dispositivo de entrada conectado ao terminal,
    • no Linux /dev/stdoutgeralmente é um link simbólico para /proc/self/fd/1, enquanto /dev/stdinum link simbólico para /proc/self/fd/0. O sistema de arquivos virtual /proctem o cuidado de mostrar a cada aplicativo /proc/selfcomo um link simbólico para /proc/<pid>, onde <pid>está o id do processo do aplicativo.
    • os links simbólicos /proc/<pid>/fdapontam para os arquivos, pipes e outras coisas abertas por um aplicativo ou herdadas de seu pai. Cada aplicativo tem a garantia de ter três descritores de arquivo abertos: 0para ler a entrada, 1para gravar a saída, 2para gravar erros. No seu caso é /dev/pts/10.

    Se você não redirecionar a saída para outro arquivo, todos os comandos executados pelo shell serão gravados no terminal. A exceção a essa regra é se o grupo de processos do seu comando for diferente do grupo de processos em primeiro plano do terminal, a gravação falhará e SIGTTOUserá enviada ao comando. Esse comportamento pode ser controlado com stty tostope stty -tostop:

    stty tostop
    echo "/dev/stdout points to the terminal, but I won't print anything" &
    stty -tostop
    echo "You can see me" &
    
    • 5
  2. Best Answer
    telcoM
    2020-02-03T05:52:55+08:002020-02-03T05:52:55+08:00

    Um programa compatível com POSIX pode esperar herdar os descritores de arquivo #0, #1 e #2 (também conhecidos pelas constantes de programação stdine stdout, stderrrespectivamente) de seu processo pai, em um estado já aberto e pronto para uso .

    No caso mais simples, de um programa de linha de comando em uma sessão logada no console de texto, sem nenhum redirecionamento aplicado, essa cadeia de herança remonta ao gettyprocesso que inicializou o dispositivo TTY para a sessão de login.

    Ao fazer login usando uma GUI, o processo do gerenciador de exibição ( gdm/kdm/sddm/lightdm/xdm/<whatever>dm) geralmente definirá a entrada e a saída /dev/nullpadrão e o erro padrão para $HOME/.xsession-errorsou algo semelhante para o primeiro processo da sessão, e esses descritores de arquivo também são herdados por todos os programas GUI iniciados na sessão, seja como parte do ambiente da área de trabalho, ou começou a usar menus ou ícones da área de trabalho.

    Para, por exemplo, sessões SSH, o sshdprocesso que bifurcou para inicializar a sessão teria alocado um par de dispositivos pseudo-TTY, apontado os stdin/out/errdescritores de arquivo para metade dele e, em seguida, exec()editado o shell do usuário. O outro lado dessa bifurcação manterá a outra metade do par de dispositivos pseudo-TTY e manipulará a criptografia/descriptografia do tráfego de entrada/saída entre a rede e o dispositivo pseudo-TTY, até que a sessão termine.

    Quando um emulador de terminal é iniciado em uma sessão GUI, ele se comporta essencialmente da mesma forma que o sshdprocesso ao inicializar uma nova sessão: ele aloca um pseudo-TTY, fork()s e uma cópia configura a sessão, incluindo descritores de arquivo apontados #0, #1 e #2 para o pseudo-TTY e, finalmente exec(), é o shell do usuário, e o outro lado do fork permanecerá lidando com a tarefa de realmente manter a representação visual da janela do terminal.

    Então, em poucas palavras, o (pseudo?) dispositivo TTY foi conectado a stdin/stdout/stderr pela coisa que inicializou sua sessão de terminal, e todos os processos que podem estar entre isso e seu aplicativo simplesmente os transmitiram em uma cadeia de herança, não fazendo nada com esses descritores de arquivo, apenas deixando-os passar para o processo filho como está.

    Quando os operadores de redirecionamento são usados ​​na linha de comando do shell, como o shell é fork()uma cópia temporária de si mesmo em preparação para realmente exec()executar o comando, logo após a fork()cópia temporária fechará o respectivo descritor de arquivo, abrirá a coisa especificada pelo operador de redirecionamento em seu lugar , e, em seguida, exec()o comando para que ele herde o(s) descritor(es) de arquivo stdin/out/err modificado(s).


    Em alguns sistemas do estilo Unix, os /dev/std*dispositivos podem ser manipulados pelo shell. Mas o Linux os torna um pouco mais "reais".

    No Linux, /dev/stdine /dev/stdoutsão /dev/stderrapenas links simbólicos antigos apontando para o sistema de /procarquivos:

    $ ls -l /dev/std*
    lrwxrwxrwx 1 root root 15 Feb  4 08:22 /dev/stderr -> /proc/self/fd/2
    lrwxrwxrwx 1 root root 15 Feb  4 08:22 /dev/stdin -> /proc/self/fd/0
    lrwxrwxrwx 1 root root 15 Feb  4 08:22 /dev/stdout -> /proc/self/fd/1
    

    Esses links são criados à medida que o sistema udevde arquivos baseado em RAM /devé inicializado na inicialização do sistema. Eles são apenas links simbólicos simples, nada mágicos lá.

    Mas /procé um sistema de arquivos totalmente virtual que reflete o estado dos processos no sistema em tempo real, e por isso possui várias propriedades "mágicas":

    • /proc/selfé um link simbólico que aponta para o /proc/<PID>diretório do processo que o analisa:
    $ ls -l /proc/self   # the PID of this ls command will be 10839
    lrwxrwxrwx 1 root root 0 Feb  4 08:22 /proc/self -> 10839/
    
    $ ls -l /proc/self   # the PID of this ls command will be 10843
    lrwxrwxrwx 1 root root 0 Feb  4 08:22 /proc/self -> 10843/
    
    • /proc/<PID>/fdé um diretório que contém links simbólicos com seus nomes correspondentes aos descritores de arquivo abertos pelo processo com <PID>, e apontando para qualquer que seja o descritor de arquivo associado .

    Então, quando um processo /dev/pts/10tenta acessar /dev/stdin, o link simbólico aponta para ele /proc/self/fd/0... e quando /proc/self/fd/0é acessado, o /procdriver do sistema de arquivos olha a tabela de processos do kernel, usa-a para encontrar a tabela de descritores de arquivos do processo que está acessando , e apresenta /proc/self/fd/0como um link simbólico para /dev/pts/10... justamente porque esse processo atualmente tem /dev/pts/10associado ao seu descritor de arquivo #0.

    No Solaris 11, os /dev/std*dispositivos são links simbólicos para o /dev/fd/diretório, que é similarmente "mágico":

    $ uname -sr
    SunOS 5.11
    $ ls -l /dev/std*
    lrwxrwxrwx   1 root     root           0 Jun 17  2019 /dev/stderr -> ./fd/2
    lrwxrwxrwx   1 root     root           0 Jun 17  2019 /dev/stdin -> ./fd/0
    lrwxrwxrwx   1 root     root           0 Jun 17  2019 /dev/stdout -> ./fd/1
    

    Aqui, o /devdriver do sistema de arquivos Solaris implementa a mágica usando nós de dispositivo no /dev/fddiretório em vez de redirecionar para o sistema de /procarquivos, como o Linux faz por motivos históricos.

    • 2
  3. ctrl-alt-delor
    2020-02-03T04:49:27+08:002020-02-03T04:49:27+08:00

    Executando um comando no shell

    Quando um comando é executado no shell, é isso que acontece.

    • shell chama fork: shell em como executar em ambos os processos.
    • novo shell é configurado std in/out/err: mas se não houver redirecionamento, ele não faz nada. O novo processo os herdou do shell original e o shell já tinha os valores corretos.
    • new shell chama execpara executar um novo programa: esse novo programa herdará valores para std in/out/erre substituirá o novo shell.

    Este novo shell é muito transitório (agora mencionado nos documentos, pois é apenas um detalhe de implementação). Não é o mesmo que um sub-shell.

    O novo comando abre/dev/stdin

    Quando o novo programa é aberto /dev/stdin, o código do sistema de arquivos no kernel vê que este é um link simbólico para /proc/self/fd/0ele, então vê que /dev/selfé um link simbólico para /proc/nnnnonde nnnn é o pid do processo, então isso aponta para /proc/nnnn/fd/0qual aponta para o arquivo, por exemplo /dev/pts/10. A abertura /dev/stdincriará um novo descritor de arquivo. Não é necessário abrir dev/stdinnormalmente, pois o descritor de arquivo 0 já aponta para o arquivo.

    (Você só precisará fazer isso se o programa não for escrito para ler stdin, mas puder ler de um arquivo.) (tudo isso também vale para stdout e stderr.)

    Os arquivos /procnão são arquivos reais (não armazenados em nenhum lugar); Estes são criados dinamicamente quando acessados ​​(nunca gravados em disco), por um sistema de arquivos, que procura os dados de estruturas de dados no kernel (não de um disco).

    • 0

relate perguntas

  • o que grep -v grep faz

  • Necessidade de algumas chamadas de sistema

  • astyle não altera a formatação do arquivo de origem

  • Como salvar um caminho com ~ em uma variável?

  • Passe o sistema de arquivos raiz por rótulo para o kernel do Linux

Sidebar

Stats

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

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

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

    • 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

    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
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • 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
    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

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