descubra quais descritores de arquivos compartilham a mesma “descrição de arquivo aberto”

16

Se eu fizer isso (em um shell tipo Bourne):

exec 3> file 4>&3 5> file 6>> file

Descreva os descritores 3 e 4, pois 4 foi dup() ed de 3, compartilhe a mesma descrição do arquivo aberto (mesmas propriedades, o mesmo deslocamento dentro do arquivo ...). Embora os descritores de arquivo 5 e 6 desse processo estejam em uma descrição de arquivo aberto diferente (por exemplo, cada um deles tem seu próprio ponteiro no arquivo).

Agora, em lsof output, tudo que vemos é:

zsh     21519 stephane    3w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG  254,2        0 10505865 /home/stephane/file

É um pouco melhor com lsof +fg :

zsh     21519 stephane    3w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG       W,AP,LG  254,2        0 10505865 /home/stephane/file

(aqui no Linux 3.16) em que vemos que o fd 6 tem flags diferentes, então tem que haver uma descrição do arquivo aberto diferente daquela em fd 3, 4 ou 5, mas a partir disso não podemos dizer que o fd 5 está em uma descrição de arquivo aberto diferente. Com -o , também podemos ver o deslocamento, mas novamente o mesmo offset não garante a mesma descrição do arquivo aberto .

Existe alguma maneira não intrusiva 1 para descobrir isso? Externamente, ou para descritores de arquivos próprios do processo?

1 . Uma abordagem heurística poderia ser alterar os sinalizadores de um fd com fcntl() e ver como outros descritores de arquivo têm seus sinalizadores atualizados, mas isso obviamente não é ideal nem à prova de erros

    
por Stéphane Chazelas 23.03.2015 / 12:51

3 respostas

1

Para o Linux 3.5 e posterior, isso pode ser feito com kcmp (3) :

KCMP_FILE

  • Check whether a file descriptor idx1 in the process pid1 refers to the same open file description (see open(2)) as file descriptor idx2 in the process pid2. The existence of two file descriptors that refer to the same open file description can occur as a result of dup(2) (and similar) fork(2), or passing file descriptors via a domain socket (see unix(7)).

A página man fornece um exemplo específico para o caso de uso que o OP fez. Note que este syscall requer que o kernel seja compilado com CONFIG_CHECKPOINT_RESTORE set.

    
por 02.10.2018 / 05:38
3

O que você deseja comparar são os struct file ponteiros para os quais os descritores de arquivo apontam. (Dentro do kernel há uma estrutura de dados task_struct para cada thread. Ela contém um ponteiro para outra estrutura chamada files_struct . E essa estrutura contém uma matriz de ponteiros, cada um para um struct file . É o struct file que contém o deslocamento de busca, os sinalizadores abertos e alguns outros campos.)

Eu não conheço nenhuma maneira visível pelo usuário de ver os ponteiros no files_struct além do uso de algumas ferramentas intrusivas. Por exemplo, o SystemTap poderia receber um PID e encontrar o task_struct correspondente e seguir os ponteiros. Se você está procurando por passivo, acho que é sobre isso. A Dell lançou uma ferramenta há um tempo atrás chamada KME (Kernel Memory Editor) que dava uma interface parecida com uma planilha para a memória do kernel e podia fazer o que você quisesse, mas nunca foi portado para 64-bit . (Eu tentei e nunca consegui trabalhar completamente, e não tinha certeza do porquê).

Um motivo pelo qual você não está encontrando lsof para ser útil é que ele também não vê esses ponteiros (mas veja a opção +f para sistemas não-Linux). Você poderia, teoricamente, comparar todos os campos no struct file e achar que as duas estruturas são iguais, mas ainda assim poderiam ser de open(2) chamadas separadas.

Dê uma olhada no script pfiles do SystemTap para obter ideias. Se você modificou para imprimir o endereço do struct file , você teria sua solução. Você também pode verificar opened_file_by_pid.stp , pois há uma função em isto anda o files_struct , ie. a tabela do descritor de arquivos, olhando para os struct file objects ...

Posso perguntar o que você está tentando realizar?

    
por 06.05.2015 / 01:12
0

Aqui está uma solução específica do Linux: / proc / self / fd é um diretório de links simbólicos para identificadores de arquivos abertos no processo atual. Você pode apenas comparar os valores do link. Isso fica mais complicado quando se usa um processo filho, porque o filho terá um / proc / self diferente porque é um link simbólico dependente de pid. Você pode solucionar esse problema usando / proc / $$ / fd em que $$ é o pid desejado.

    
por 14.04.2015 / 17:13