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 / 413204
Accepted
marked-down
marked-down
Asked: 2017-12-27 19:50:57 +0800 CST2017-12-27 19:50:57 +0800 CST 2017-12-27 19:50:57 +0800 CST

Como o Unix acompanha o diretório de trabalho de um usuário ao navegar no sistema de arquivos?

  • 772

Digamos que eu faça login em um shell em um sistema unix e comece a digitar comandos. Eu inicialmente começo no diretório inicial do meu usuário ~. Eu poderia de lá cdpara baixo para o diretório Documents.

O comando para alterar o diretório de trabalho aqui é muito simples de entender intuitivamente: o nó pai possui uma lista de nós filhos que pode acessar e, presumivelmente, usa uma variante (otimizada) de uma pesquisa para localizar a existência de um nó filho com o nomeie o usuário digitado e o diretório de trabalho é então "alterado" para corresponder a isso - corrija-me se eu estiver errado aí. Pode até ser mais simples que o shell simplesmente "ingenuamente" tente acessar o diretório exatamente de acordo com os desejos do usuário e quando o sistema de arquivos retornar algum tipo de erro, o shell exibirá uma resposta correspondente.

O que me interessa, no entanto, é como o mesmo processo funciona quando navego para cima em um diretório, ou seja, para um pai ou pai de um pai.

Dada a minha localização desconhecida, presumivelmente "cega" Documents, um dos possivelmente muitos diretórios em toda a árvore do sistema de arquivos com esse nome, como o Unix determina onde devo ser colocado a seguir? Ele faz uma referência pwde examina isso? Se sim, como pwdrastreia o estado de navegação atual?

filesystems pwd
  • 3 3 respostas
  • 3778 Views

3 respostas

  • Voted
  1. Best Answer
    JdeBP
    2017-12-28T00:20:40+08:002017-12-28T00:20:40+08:00

    As outras respostas são simplificações excessivas, cada uma apresentando apenas partes da história e estão erradas em alguns pontos.

    Há duas maneiras pelas quais o diretório de trabalho é rastreado:

    • Para cada processo, na estrutura de dados do espaço do kernel que representa esse processo, o kernel armazena duas referências vnode aos vnodes do diretório de trabalho e ao diretório raiz desse processo. A primeira referência é definida pelas chamadas de sistema chdir()e , a última por . Pode-se vê-los indiretamente em sistemas operacionais Linux ou através do comando no FreeBSD e similares:fchdir()chroot()/procfstat

      % fstat -p $$|cabeça -n 5
      USER CMD PID FD MOUNT INUM MODE SZ|DV R/W
      JdeBP zsh 92648 texto / 24958 -r-xr-xr-x 702360 r
      JdeBP zsh 92648 ctty /dev 148 crw--w---- pts/4 rw
      JdeBP zsh 92648 wd /usr/home/JdeBP 4 drwxr-xr-x 124 r
      JdeBP zsh 92648 root / 4 drwxr-xr-x 35 r
      %

      Quando a resolução do nome do caminho opera, ela começa em um ou outro desses vnodes referenciados, dependendo se o caminho é relativo ou absoluto. (Existe uma família de …at()chamadas de sistema que permite que a resolução do nome do caminho comece no vnode referenciado por um descritor de arquivo aberto (diretório) como uma terceira opção.)

      No microkernel Unices, a estrutura de dados está no espaço do aplicativo, mas o princípio de manter referências abertas a esses diretórios permanece o mesmo.

    • Internamente, dentro de shells como Z, Korn, Bourne Again, C e Almquist shell, o shell também controla o diretório de trabalho usando a manipulação de string de uma variável de string interna. Ele faz isso sempre que tem motivo para chamar chdir().

      Se alguém mudar para um nome de caminho relativo, ele manipula a string para anexar esse nome. Se alguém mudar para um nome de caminho absoluto, ele substituirá a string pelo novo nome. Em ambos os casos, ele ajusta a string para remover .e ..componentes e perseguir links simbólicos substituindo-os por seus nomes vinculados. ( Aqui está o código do shell Z para isso , por exemplo.)

      O nome na variável de string interna é rastreado por uma variável de shell chamada PWD(ou cwdnos shells C). Isso é exportado convencionalmente como uma variável de ambiente (chamada PWD) para programas gerados pelo shell.

    Esses dois métodos de rastrear coisas são revelados pelas opções -Pe para os comandos internos do shell e pelas diferenças entre os comandos internos do shell e tanto o comando quanto os comandos internos de coisas como (entre outros) VIM e NeoVIM.-Lcdpwdpwd/bin/pwdpwd

    % mkdir a ; ln -sab 
    % (cd b; pwd; /bin/pwd; printenv PWD)
    /usr/home/JdeBP/b
    /usr/home/JdeBP/a
    /usr/home/JdeBP/b
    % (cd b; pwd -P; /bin/pwd -P)
    /usr/home/JdeBP/a
    /usr/home/JdeBP/a
    % (cd b; pwd -L; /bin/pwd -L)
    /usr/home/JdeBP/b
    /usr/home/JdeBP/b
    % (cd -P b; pwd; /bin/pwd; printenv PWD)
    /usr/home/JdeBP/a
    /usr/home/JdeBP/a
    /usr/home/JdeBP/a
    % (cd b; PWD=/olá/lá /bin/pwd -L)
    /usr/home/JdeBP/a
    %

    Como você pode ver: obter o diretório de trabalho "lógico" é uma questão de olhar para a PWDvariável shell (ou variável de ambiente se não for o programa shell); considerando que obter o diretório de trabalho "físico" é uma questão de chamar a getcwd()função de biblioteca.

    O funcionamento do /bin/pwdprograma quando a -Lopção é utilizada é um tanto sutil. Ele não pode confiar no valor da PWDvariável de ambiente que herdou. Afinal, ele não precisa ter sido invocado por um shell e os programas intervenientes podem não ter implementado o mecanismo do shell de fazer com que a PWDvariável de ambiente sempre rastreie o nome do diretório de trabalho. Ou alguém pode fazer o que eu acabei de fazer.

    Então, o que ele faz é (como diz o padrão POSIX) verificar se o nome fornecido em PWDretorna a mesma coisa que o nome ., como pode ser visto com um rastreamento de chamada do sistema:

    % ln -sac 
    % (cd b; truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd') 
    stat("/usr/home/JdeBP/b",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0) 
    stat(".",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize =131072 }) = 0 (0x0)
    /usr/home/JdeBP/b
    % (cd b; PWD=/usr/local/etc truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd') 
    stat("/usr/local/etc" ,{ mode=drwxr-xr-x ,inode=14835,size=158,blksize=10240 }) = 0 (0x0) 
    stat(".",{ mode=drwxr-xr-x ,inode=120932,size=2 ,blksize=131072 }) = 0 (0x0)
    __getcwd("/usr/home/JdeBP/a",1024) = 0 (0x0)
    /usr/home/JdeBP/a
    % (cd b; PWD=/hello/there truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd') 
    stat("/hello/there",0x7fffffffe730) ERR #2 'Não existe tal arquivo ou diretório' 
    __getcwd("/usr/home/JdeBP/a",1024) = 0 (0x0)
    /usr/home/JdeBP/a
    % (cd b; PWD=/usr/home/JdeBP/c truss /bin/pwd -L 3>&1 1>&2 2>&3 | grep -E '^stat|__getcwd') 
    stat("/usr/home/ JdeBP/c",{ mode=drwxr-xr-x ,inode=120932,size=2,blksize=131072 }) = 0 (0x0) 
    stat(".",{ mode=drwxr-xr-x ,inode=120932 ,size=2,blksize=131072 }) = 0 (0x0)
    /usr/home/JdeBP/c
    %

    Como você pode ver: ele só chama getcwd()se detectar uma incompatibilidade; e pode ser enganado definindo PWDuma string que de fato nomeia o mesmo diretório, mas por uma rota diferente.

    A getcwd()função da biblioteca é um assunto por si só. Mas para resumir:

    • Originalmente, era puramente uma função de biblioteca, que construía um nome de caminho do diretório de trabalho de volta à raiz, tentando repetidamente procurar o diretório de trabalho no ..diretório. Ele parou quando atingiu um loop onde ..era o mesmo que seu diretório de trabalho ou quando houve um erro ao tentar abrir o próximo ... Isso seria um monte de chamadas de sistema nos bastidores.
    • Hoje em dia a situação é um pouco mais complexa. No FreeBSD, por exemplo (isso também é verdade para outros sistemas operacionais), é uma verdadeira chamada de sistema, como você pode ver no rastreamento de chamada de sistema fornecido anteriormente. Todo o percurso do diretório de trabalho vnode até a raiz é feito em uma única chamada de sistema, que aproveita coisas como o acesso direto do código do modo kernel ao cache de entrada do diretório para fazer as pesquisas de componente de nome de caminho com muito mais eficiência.

      No entanto, observe que mesmo no FreeBSD e nesses outros sistemas operacionais, o kernel não rastreia o diretório de trabalho com uma string.

    Navegar para ..é novamente um assunto em si. Outro resumo: embora os diretórios convencionalmente (embora, como já mencionado, isso não seja necessário) contenham uma ..estrutura de dados de diretório real no disco, o kernel rastreia o diretório pai de cada diretório vnode e pode, assim, navegar para o ..vnode de qualquer diretório de trabalho. Isso é um pouco complicado pelo ponto de montagem e pelos mecanismos raiz alterados, que estão além do escopo desta resposta.

    Aparte

    O Windows NT, de fato, faz algo semelhante. Há um único diretório de trabalho por processo, definido pela SetCurrentDirectory()chamada da API e rastreado por processo pelo kernel por meio de um identificador de arquivo aberto (interno) para esse diretório; e há um conjunto de variáveis ​​de ambiente que os programas Win32 (não apenas os interpretadores de comandos, mas todos os programas Win32) usam para rastrear os nomes de vários diretórios de trabalho (um por unidade), acrescentando ou substituindo-os sempre que mudam de diretório.

    Convencionalmente, diferentemente do caso dos sistemas operacionais Unix e Linux, os programas Win32 não exibem essas variáveis ​​de ambiente para os usuários. Às vezes, pode-se vê-los em subsistemas do tipo Unix rodando no Windows NT, assim como usando os comandos dos interpretadores de SETcomandos de uma maneira particular.

    Leitura adicional

    • " pwd" . The Open Group Base Specifications Problema 7. IEEE 1003.1:2008. O Grupo Aberto. 2016.
    • "Resolução de nome de caminho" . The Open Group Base Specifications Problema 7. IEEE 1003.1:2008. O Grupo Aberto. 2016.
    • https://askubuntu.com/a/636001/43344
    • Como os arquivos são abertos no unix?
    • para que serve o inode, no FreeBSD ou Solaris
    • Variável de ambiente estranha!::=::\ no Cygwin
    • Por que o CDPATH não funciona conforme documentado nos manuais?
    • Como posso definir o zsh para usar caminhos físicos?
    • Entrando em um diretório vinculado por um link
    • 79
  2. Johan Myréen
    2017-12-27T23:03:07+08:002017-12-27T23:03:07+08:00

    O kernel não mantém registro de diretórios ou nomes de arquivos; um arquivo ou diretório é representado no kernel por um par inode/dispositivo. Chamadas de sistema como chdir(), open(), etc. recebem um caminho como parâmetro, que pode ser absoluto (ex. /etc/passwd), ou relativo ao diretório atual (exemplos: Documents, ..). Quando um processo é executado chdir("Documents"), uma pesquisa é feita Documentsno diretório de trabalho atual e o diretório de trabalho do processo é atualizado para se referir a esse diretório. Do ponto de vista do kernel, não há nada de especial no nome "..", é apenas uma convenção no sistema de arquivos que ..se refere ao diretório pai.

    A getcwd()função não é uma chamada de sistema, mas uma função de biblioteca que tem que trabalhar até o diretório raiz, registrando os nomes dos componentes do caminho no caminho.

    • 1
  3. user267857
    2017-12-29T04:46:09+08:002017-12-29T04:46:09+08:00

    Curiosamente, tradicionalmente cd ..é muito mais simples do que pwd. Os diretórios nomeados ..são colocados explicitamente no sistema de arquivos. O sistema rastreia o dispositivo/inode do diretório atual, então, cd ..ou mais precisamente, a chamada do sistema chdir("..")envolve apenas procurar o nome ".." no arquivo pertencente ao inode do diretório atual e alterar o dispositivo/inode do diretório atual para o valor encontrado lá.

    pwd(mais precisamente /bin/pwd) segue ..os links sucessivamente e lê os respectivos diretórios até encontrar o inode de onde veio, montando a lista desses nomes ao contrário até chegar ao diretório raiz (notavelmente não contendo uma ..entrada).

    Agora, este é o comportamento básico original de baixo nível. Em vez disso , os comandos reais do shell pwddependem de uma variedade de técnicas de armazenamento em cache do nome do caminho atual. Mas, no fundo, é apenas seu inode que é realmente conhecido. Isso implica que, uma vez que os links simbólicos são usados ​​para navegar nos diretórios, as noções de nome do diretório de trabalho atual do shell atual e do sistema /bin/pwdpodem divergir.

    • 0

relate perguntas

  • Qual sistema de arquivos devo usar em um cartão SD em um NAS?

  • Como saber antecipadamente se um .zip tem um diretório pai dentro

  • Disco alocado dinamicamente do Virtualbox *.vdi continua crescendo

  • du/df e ls relatando diferentes usos de disco

  • Como os desenvolvedores do kernel Linux lidam com seu trabalho com milhões de linhas de código? É um método? [fechado]

Sidebar

Stats

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

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

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

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +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
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +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
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +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