O que está em uma DLL e como funciona?

86

Estou sempre fazendo referência a DLLs em meu código C #, mas elas permanecem um mistério que gostaria de esclarecer. Esta é uma espécie de despejo cerebral de perguntas sobre DLLs.

Eu entendo que uma DLL é uma biblioteca vinculada dinamicamente, o que significa que outro programa pode acessar essa biblioteca em tempo de execução para obter "funcionalidade". No entanto, considere o seguinte projeto ASP.NET com Web.dlle Business.dll( Web.dllé a funcionalidade de front end e faz referência Business.dlla tipos e métodos).

  1. Em que ponto o Web.dlllink está dinamicamente Business.dll? Você percebe muitas dificuldades no disco rígido do Windows para tarefas aparentemente pequenas ao usar o Word (etc.) e eu imagino que o Word está desativando e vinculando dinamicamente a funcionalidade de outras DLLs?

    1a. Além disso, o que carrega e vincula a DLL - o sistema operacional ou alguma estrutura de tempo de execução como a estrutura .NET?

    1b. Qual é o processo de "vinculação"? São feitas verificações de compatibilidade? Carregando na mesma memória? O que realmente significa vincular?

  2. O que realmente executa o código na DLL? Ele é executado pelo processador ou há outro estágio de tradução ou compilação antes que o processador compreenda o código dentro da DLL?

    2a. No caso de uma DLL construída em C # .NET, o que está executando isso: a estrutura .NET ou o sistema operacional diretamente?

  3. Uma DLL do Linux funciona em um sistema Windows (se tal existir) ou são específicas do sistema operacional?

  4. As DLLs são específicas para uma determinada estrutura? Uma DLL criada com C # .NET pode ser usada por uma DLL criada com, por exemplo, Borland C ++?

    4a. Se a resposta a 4 for "não", qual é o objetivo de uma DLL? Por que as várias estruturas não usam seus próprios formatos para arquivos vinculados? Por exemplo: um .exe integrado ao .NET sabe que um tipo de arquivo .abc é algo que pode ser vinculado a seu código.

  5. Voltando à Web.dll/ Business.dllexemplo - para obter um tipo de classe de cliente eu preciso de referência Business.dllde Web.dll. Isso deve significar que Business.dllcontém algum tipo de especificação sobre o que uma classe de cliente realmente é. Se eu tivesse compilado meu Business.dllarquivo em, digamos, Delphi: o C # entenderia e seria capaz de criar uma classe de cliente, ou há algum tipo de informação de cabeçalho ou algo que diz "ei, desculpe, você só pode me usar de outra DLL Delphi" ?

    5a. O mesmo se aplica a métodos; posso escrever um CreateInvoice()método em uma DLL, compilá-lo em C ++ e, em seguida, acessá-lo e executá-lo em C #? O que me impede ou me permite de fazer isso?

  6. Sobre o assunto de sequestro de DLL, certamente a DLL de substituição (ruim) deve conter as assinaturas e tipos de método exatos como aquele que está sendo sequestrado. Suponho que isso não seria difícil de fazer se você pudesse descobrir quais métodos estão disponíveis na DLL original.

    6a. O que em meu programa C # está decidindo se posso acessar outra DLL? Se minha DLL sequestrada contivesse exatamente os mesmos métodos e tipos do original, mas fosse compilada em outro idioma, isso funcionaria?

O que é importação de DLL e registro de DLL?

Remotec
fonte
21
Esta pergunta pode ser a resposta mais longa da história do SO.
Matti Virkkunen,
4
Deveria ter sido 12 perguntas separadas.
Henk Holterman,
2
Esta é uma pergunta incrível, mas eu realmente concordo com @Chaos e @Matti. Esta questão precisa de mais foco e pode / deve ser dividida em várias questões diferentes.
Chris Thompson,
3
Foi um pouco
complicado
1
Deve ser um wiki da comunidade agora.
leppie

Respostas:

74

Em primeiro lugar, você precisa entender a diferença entre dois tipos muito diferentes de DLLs. A Microsoft decidiu usar as mesmas extensões de arquivo (.exe e .dll) com .NET (código gerenciado) e código nativo, no entanto, DLLs de código gerenciado e DLLs nativas são muito diferentes por dentro.

1) Em que ponto o web.dll se vincula dinamicamente ao business.dll? Você percebe muito no Windows HDD atrapalhando para tarefas aparentemente pequenas ao usar o Word etc e eu imagino que esse Word desligue e conecte dinamicamente a funcionalidade de outras DLLs?

1) No caso do .NET, as DLLs geralmente são carregadas sob demanda quando o primeiro método que tenta acessar qualquer coisa da DLL é executado. É por isso que você pode obter TypeNotFoundExceptions em qualquer lugar do seu código se uma DLL não puder ser carregada. Quando algo como o Word repentinamente começa a acessar muito o HDD, é provável que esteja trocando (obtendo dados que foram trocados para o disco para liberar espaço na RAM)

1a) Além disso, o que carrega e vincula a DLL - o O / S ou alguma estrutura de tempo de execução como a estrutura .Net?

1a) No caso de DLLs gerenciadas, o framework .NET é o que carrega, o JIT compila (compila o bytecode .NET em código nativo) e vincula as DLLs. No caso de DLLs nativas, é um componente do sistema operacional que carrega e vincula a DLL (nenhuma compilação é necessária porque as DLLs nativas já contêm código nativo).

1b) Qual é o processo de "vinculação"? São feitas verificações de compatibilidade? Carregando na mesma memória? O que realmente significa vincular?

1b) Linking é quando as referências (por exemplo, chamadas de método) no código de chamada para símbolos (por exemplo, métodos) na DLL são substituídas pelos endereços reais das coisas na DLL. Isso é necessário porque os endereços eventuais das coisas na DLL não podem ser conhecidos antes de serem carregados na memória.

2) O que realmente executa o código na DLL? Ele é executado pelo processador ou há outro estágio de tradução ou compilação antes que o processador compreenda o código dentro da DLL?

2) No Windows, os arquivos .exe e os arquivos .dll são bastante idênticos. Os arquivos .exe e .dll nativos contêm código nativo (o mesmo material que o processador executa), portanto, não há necessidade de traduzir. Os arquivos .exe e .dll gerenciados contêm bytecode .NET que é primeiro compilado por JIT (traduzido em código nativo).

2a) No caso de uma DLL construída a partir de C # .net o que está executando isso? A estrutura .Net ou o sistema operacional diretamente?

2a) Depois que o código foi compilado JIT, ele é executado exatamente da mesma maneira que qualquer código.

3) Uma DLL do Linux, digamos, funciona em um sistema Windows (se tal existir) ou são específicas do sistema operacional?

3) DLLs gerenciadas podem funcionar como estão, contanto que as estruturas em ambas as plataformas estejam atualizadas e quem escreveu a DLL não quebrou a compatibilidade deliberadamente usando chamadas nativas. DLLs nativas não funcionarão da mesma forma, pois os formatos são diferentes (embora o código de máquina interno seja o mesmo, se ambos forem para a mesma plataforma de processador). A propósito, no Linux, "DLLs" são conhecidos como arquivos .so (objeto compartilhado).

4) Eles são específicos para uma estrutura particular? Uma DLL construída usando C # .Net pode ser usada por uma DLL construída com Borland C ++ (apenas exemplo)?

4) DLLs gerenciadas são específicas do .NET framework, mas naturalmente funcionam com qualquer linguagem compatível. DLLs nativas são compatíveis, desde que todos usem as mesmas convenções (convenções de chamada (como os argumentos de função são passados ​​no nível de código de máquina), nomenclatura de símbolo, etc)

5) Voltando ao exemplo web.dll / business.dll. Para obter um tipo de cliente de classe, preciso referenciar business.dll de web.dll. Isso deve significar que business.dll contém uma especificação de algum tipo do que uma classe de cliente realmente é. Se eu tivesse compilado meu arquivo business.dll em digamos que Delphi iria C # entendê-lo e ser capaz de criar uma classe de cliente - ou há algum tipo de informação de cabeçalho ou algo que diz "ei, desculpe, você só pode me usar de outra dll Delphi" .

5) DLLs gerenciadas contêm uma descrição completa de cada classe, método, campo, etc. que contêm. O AFAIK Delphi não oferece suporte ao .NET, então criaria DLLs nativas, que não podem ser usadas no .NET diretamente. Você provavelmente será capaz de chamar funções com PInvoke, mas as definições de classe não serão encontradas. Eu não uso Delphi, então não sei como ele armazena informações de tipo com DLLs. C ++, por exemplo, depende de arquivos de cabeçalho (.h) que contêm as declarações de tipo e devem ser distribuídos com a DLL.

6) Sobre o assunto de sequestro de DLL, certamente a DLL de substituição (ruim) deve conter as assinaturas de método exatas, tipos como o que está sendo sequestrado. Suponho que isso não seria difícil de fazer se você pudesse descobrir quais métodos etc. estavam disponíveis na DLL original.

6) Na verdade, não é difícil fazer isso se você puder alternar facilmente a DLL. A assinatura de código pode ser usada para evitar isso. Para que alguém substitua uma DLL assinada, é necessário conhecer a chave de assinatura, que é mantida em segredo.

6a) Uma pergunta repetida aqui, mas isso remete ao que no meu programa C # está decidindo se eu posso acessar outra DLL? Se minha DLL sequestrada contivesse exatamente os mesmos métodos e tipos do original, mas fosse compilada em outro idioma, isso funcionaria?

6a) Funcionaria desde que fosse uma DLL gerenciada, feita com qualquer linguagem .NET.

  • O que é DLL importando? e registro dll?

"Importação de DLL" pode significar muitas coisas, geralmente significa fazer referência a um arquivo DLL e usar coisas nele.

O registro DLL é algo que é feito no Windows para registrar globalmente os arquivos DLL como componentes COM para torná-los disponíveis para qualquer software no sistema.

Matti Virkkunen
fonte
3
Eu acrescentaria ao # 4 que o .NET pode traduzir DLLs para que sejam compatíveis com qualquer programa nativo que entenda / use COM (Common Object Model). Muito boas respostas tho.
MerickOWA,
7

Um arquivo .dll contém código compilado que você pode usar em seu aplicativo.

Às vezes, a ferramenta usada para compilar o .dll é importante, às vezes não. Se você pode fazer referência ao .dll em seu projeto, não importa qual ferramenta foi usada para codificar as funções expostas do .dll.

A vinculação acontece em tempo de execução, ao contrário de bibliotecas vinculadas estaticamente, como suas classes, que se vinculam em tempo de compilação.

Você pode pensar em um .dll como uma caixa preta que fornece algo de que seu aplicativo precisa e que você não deseja escrever. Sim, alguém que entende a assinatura do .dll poderia criar outro arquivo .dll com um código diferente dentro dele e seu aplicativo de chamada não poderia saber a diferença.

HTH

Beth
fonte
6

1) Em que ponto o web.dll se vincula dinamicamente ao business.dll? Você percebe muito no Windows HDD atrapalhando para tarefas aparentemente pequenas ao usar o Word etc e eu imagino que esse Word desligue e conecte dinamicamente a funcionalidade de outras DLLs?

1) Acho que você está confundindo link com carregamento. O link é quando todas as verificações e balanços são testados para ter certeza de que o que é pedido está disponível. No momento do carregamento, partes da dll são carregadas na memória ou trocadas para o arquivo de paginação. Esta é a atividade HD que você está vendo.

A vinculação dinâmica é diferente da vinculação estática, pois na vinculação estática todo o código do objeto é colocado no .exe principal no momento do link. Com a vinculação dinâmica, o código do objeto é colocado em um arquivo separado (dll) e carregado em um momento diferente do .exe.

A vinculação dinâmica pode ser implícita (ou seja, os links do aplicativo com uma biblioteca de importação) ou explícita (ou seja, o aplicativo usa LoadLibrary (ex) para carregar a dll).

No caso implícito, / DELAYLOAD pode ser usado para adiar o carregamento da dll até que o aplicativo realmente precise dela. Caso contrário, pelo menos algumas partes dele são carregadas (mapeadas no espaço de endereço do processo) como parte da inicialização do processo. A dll também pode solicitar que nunca seja descarregada enquanto o processo estiver ativo.

COM usa LoadLibrary para carregar dlls COM. Observe que, mesmo no caso implícito, o sistema está usando algo semelhante a LoadLibrary para carregar a dll na inicialização do processo ou no primeiro uso.

2) O que realmente executa o código na DLL? Ele é executado pelo processador ou há outro estágio de tradução ou compilação antes que o processador compreenda o código dentro da DLL?

2) Dlls contêm código de objeto exatamente como .exes. O formato do arquivo dll é quase idêntico ao formato de um arquivo exe. Ouvi dizer que há apenas um bit diferente nos cabeçalhos dos dois arquivos.

No caso de uma DLL criada em C # .net, a estrutura .Net está executando-a.

3) Uma DLL do Linux, digamos, funciona em um sistema Windows (se tal existir) ou são específicas do sistema operacional?

3) DLLs são específicas da plataforma.

4) Eles são específicos para uma estrutura particular? Uma DLL construída usando C # .Net pode ser usada por uma DLL construída com Borland C ++ (apenas exemplo)?

4) As DLLs podem interoperar com outras estruturas se um cuidado especial for tomado ou algum código de cola adicional for escrito.

As DLLs são muito úteis quando uma empresa vende vários produtos com recursos de sobreposição. Por exemplo, mantenho uma dll de i / o raster que é usada por mais de 30 produtos diferentes na empresa. Se você tiver vários produtos instalados, uma atualização da dll pode atualizar todos os produtos para novos formatos raster.

5) Voltando ao exemplo web.dll / business.dll. Para obter um tipo de cliente de classe, preciso referenciar business.dll de web.dll. Isso deve significar que business.dll contém uma especificação de algum tipo do que uma classe de cliente realmente é. Se eu tivesse compilado meu arquivo business.dll em digamos que Delphi iria C # entendê-lo e ser capaz de criar uma classe de cliente - ou há algum tipo de informação de cabeçalho ou algo que diz "ei, desculpe, você só pode me usar de outra dll Delphi" .

5) Dependendo da plataforma, os recursos de uma dll são apresentados de várias maneiras, por meio de arquivos .h, arquivos .tlb ou outras formas em .net.

6) Sobre o assunto de sequestro de DLL, certamente a DLL de substituição (ruim) deve conter as assinaturas de método exatas, tipos como o que está sendo sequestrado. Suponho que isso não seria difícil de fazer se você pudesse descobrir quais métodos etc. estavam disponíveis na DLL original.

6) dumpbin / exports e dumbin / import são ferramentas interessantes para usar em .exe e .dlls

Edgman
fonte
3) DLLs são específicas da plataforma
Henk Holterman,