Se eu fizer (em um shell tipo Bourne):
exec 3> file 4>&3 5> file 6>> file
Os descritores de arquivo 3 e 4, desde que 4 foi dup()
editado a partir de 3, compartilham a mesma descrição de 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 diferente de arquivo aberto (por exemplo, cada um deles tem seu próprio ponteiro no arquivo).
Agora, na lsof
saída, tudo o 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), pois vemos que o fd 6 tem sinalizadores diferentes; portanto, deve haver uma descrição de arquivo aberto diferente daquela do fd 3, 4 ou 5, mas disso não podemos dizer que o fd 5 está em um descrição diferente do arquivo aberto . Com -o
, também pudemos ver o deslocamento, mas novamente o mesmo deslocamento não garante a mesma descrição de arquivo aberto .
Existe alguma não-intrusiva 1 maneira de descobrir isso? Externamente, ou para os próprios descritores de arquivo de um processo?
1 . Uma abordagem heurística poderia ser alterar os sinalizadores de um fd fcntl()
e ver com que outros descritores de arquivos têm seus sinalizadores atualizados como resultado, mas isso obviamente não é o ideal nem a prova de idiotas
fonte
Respostas:
Para o Linux 3.5 e posteriores, isso pode ser realizado com o kcmp (3) :
A página de manual fornece um exemplo específico para o OP de caso de uso solicitado. Note que este syscall requer que o kernel seja compilado com
CONFIG_CHECKPOINT_RESTORE
set.fonte
struct file *
ponteiros.O que você deseja comparar são os
struct file
indicadores apontados pelos descritores de arquivo. (Dentro do kernel há umatask_struct
estrutura de dados para cada thread. Ele contém um ponteiro para outra estrutura chamada thefiles_struct
. E essa estrutura contém uma matriz de ponteiros, cada um para A.struct file
É ostruct file
que retém o deslocamento de busca, os sinalizadores abertos e um alguns outros campos.)Não conheço nenhuma maneira visível do usuário para ver os ponteiros
files_struct
além do uso de algumas ferramentas intrusivas. Por exemplo, o SystemTap pode receber um PID e encontrar o correspondentetask_struct
e seguir os ponteiros. Se você está procurando passivo, acho que é isso. A Dell lançou uma ferramenta há muito tempo chamada KME (Kernel Memory Editor), que fornecia uma interface semelhante a uma planilha para armazenar a memória do kernel e poderia fazer o que você deseja, mas nunca foi portada para 64 bits. (Tentei e nunca o fiz funcionar completamente e não sabia ao certo por quê.)Uma razão pela qual você não está achando
lsof
útil é que ele também não vê esses ponteiros (mas veja a+f
opção para sistemas não Linux). Teoricamente, você pode comparar todos os camposstruct file
e pensar que as duas estruturas são iguais, mas ainda assim podem ser deopen(2)
chamadas separadas .Dê uma olhada no script SystemTap pfiles para obter idéias. Se você o modificou para imprimir o endereço do
struct file
, teria sua solução. Você também pode verificar o arquivo open_file_by_pid.stp, já que há uma função nele que percorre ofiles_struct
, ie. a tabela do descritor de arquivo, olhando para osstruct file
objetos ...Posso perguntar o que você está tentando realizar?
fonte
probe begin
bloco e faça com que ele use afor_each_process
macro em um bloco de código C incorporado no script (você precisará usar o SystemTap no modo "guru" para incorporar o código C). De fato, para tornar isso interessante (!), Você pode usar uma das matrizes associativas do SystemTap; use ofiles_struct
endereço como chave e uma lista de PIDs / TIDs como valores. Agora você tem uma lista de todos os arquivos abertos e quais tarefas estão sendo compartilhadas (elas podem ser compartilhadas entre pai / filho). Responda novamente se quiser discutir o SystemTap.Aqui está uma solução específica para 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. Fica mais complicado ao usar um processo filho, porque a criança 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.
fonte