O que significam "ligações estáticas" e "ligações dinâmicas"?

ouço frequentemente os Termos 'ligados estaticamente' e' ligados dinamicamente', frequentemente em referência a um código escrito em C, C++ ou C#. Do que é que eles estão a falar, exactamente, e do que é que eles estão a ligar?

Author: UnkwnTech, 2008-11-22

5 answers

Existem (na maioria dos casos, descartando o código interpretado) duas fases na passagem do código fonte (o que você escreve) para o código executável (o que você executa).

A primeira é a compilação que transforma o código-fonte em módulos de objectos.

O segundo, linking, é o que combina módulos de objetos juntos para formar um executável.

A distinção é feita para, entre outras coisas, permitir que bibliotecas de terceiros sejam incluídas em seu executável sem que você veja seu código fonte (como bibliotecas para acesso a bases de dados, comunicações em rede e interfaces gráficas de usuário), ou para compilar código em diferentes línguas (C e código de montagem, por exemplo) e, em seguida, ligá-los todos juntos.

Quando você tematicamente ligar um ficheiro a um executável, o conteúdo desse ficheiro é incluído na altura da ligação. Em outras palavras, o conteúdo do arquivo é fisicamente inserido no executável que você vai executar.

Quando se liga dinamicamente , a o ponteiro para o arquivo que está sendo ligado (o nome do arquivo, por exemplo) está incluído no executável e o conteúdo desse arquivo não está incluído na hora do link. Só quando você executaro executável é que estes arquivos dinamicamente ligados são comprados e eles só são comprados na cópia em memória do executável, não o que está no disco.

É basicamente um método de ligação diferida. Há um método mais diferido (chamado de ligação tardia em alguns casos). sistemas) que não trará o arquivo dinamicamente ligado até que você realmente tente chamar uma função dentro dele.

Os ficheiros com ligações estáticas estão 'bloqueados' ao executável no momento da ligação, por isso nunca mudam. Um arquivo ligado dinamicamente referenciado por um executável pode mudar apenas substituindo o arquivo no disco.

Isto permite actualizações à funcionalidade sem ter de voltar a ligar o código; o carregador volta a ligar-se sempre que o executa.

Isto é bom e mau. permite a fácil atualizações e correções de bugs, por outro, pode levar a programas de deixar de funcionar se as atualizações são incompatíveis - isso às vezes é responsável pela temida "DLL hell" que algumas pessoas mencionam em que os aplicativos podem ser quebrados, se você substituir uma biblioteca dinamicamente vinculada com aquele que não é compatível (os desenvolvedores que este deve esperar ser caçados e punidos severamente, por sinal).

Como um exemplo , vamos olhar para o caso de um usuário compilando o seu ficheiro main.c para ligação estática e dinâmica.

Phase     Static                    Dynamic
--------  ----------------------    ------------------------
          +---------+               +---------+
          | main.c  |               | main.c  |
          +---------+               +---------+
Compile........|.........................|...................
          +---------+ +---------+   +---------+ +--------+
          | main.o  | | crtlib  |   | main.o  | | crtimp |
          +---------+ +---------+   +---------+ +--------+
Link...........|..........|..............|...........|.......
               |          |              +-----------+
               |          |              |
          +---------+     |         +---------+ +--------+
          |  main   |-----+         |  main   | | crtdll |
          +---------+               +---------+ +--------+
Load/Run.......|.........................|..........|........
          +---------+               +---------+     |
          | main in |               | main in |-----+
          | memory  |               | memory  |
          +---------+               +---------+

Você pode ver no caso estático que o programa principal e a biblioteca de tempo de execução C estão ligados em conjunto no tempo de ligação (pelos desenvolvedores). Uma vez que o usuário normalmente não pode re-ligar o executável, eles estão presos com o comportamento da biblioteca.

No caso dinâmico, o programa principal Está ligado à biblioteca de importação de tempo de execução C (algo que declara o que está na biblioteca dinâmica, mas na verdade não define Isso). Isso permite que o linker para link, mesmo que o código atual está faltando.

Então, em tempo de execução, o carregador do sistema operacional faz uma ligação tardia do programa principal com o DLL do C (dynamic link library ou shared library ou outra nomenclatura).

O dono do tempo de execução C pode largar um DLL novo a qualquer momento para fornecer actualizações ou correcções de erros. Como já foi referido, isto tem vantagens e desvantagens.

 461
Author: paxdiablo, 2011-12-13 07:48:21
Acho que uma boa resposta a esta pergunta deve explicar o que é ligar .

Quando você compila algum código C (por exemplo), ele é traduzido para a linguagem de máquina. Apenas uma sequência de bytes que, quando executado, faz com que o processador adicione, subtraia, compare, "goto", leia memória, escreva memória, esse tipo de coisa. Esta coisa é armazenada em objeto (.O) arquivos.

Há muito tempo, os cientistas informáticos inventaram esta coisa da "sub-rotina". Execute-este-pedaço-de-código-e-retorno-aqui. Não demorou muito para que eles percebessem que as sub-rotinas mais úteis poderiam ser armazenadas em um lugar especial e usadas por qualquer programa que precisasse delas. Agora, nos primeiros dias, os programadores teriam de introduzir o endereço de memória em que estas sub-rotinas estavam localizadas. Algo como ... Isto foi tedioso e problemático se esses endereços de memória alguma vez precisar ser mudado. Então, o processo foi automatizado. Você escreve um programa isso chama printf(), e o compilador não sabe o endereço de memória de printf. Então o compilador apenas escreve CALL 0x0000, e adiciona uma nota ao arquivo objeto dizendo " deve substituir este 0x0000 com a localização da memória de printf ".

Ligação estática significa que o programa linker (o GNU é chamado ld) adiciona o código da máquina printf directamente ao seu ficheiro executável, e altera o 0x0000 para o endereço de printf. Isto acontece quando o seu executável é criado.

Dinâmica Ligação significa que o passo acima não acontece. O ficheiro executável still tem uma nota que diz "deve substituir 0x000 com a localização da memória do printf". O carregador do sistema operacional precisa encontrar o código printf, carregá-lo na memória e corrigir o endereço de chamada, cada vez que o programa é executado.

É comum os programas chamarem algumas funções que serão ligadas de forma estática (funções de biblioteca padrão como printf são geralmente ligadas de forma estática) e outras funções que estão dinamicamente ligadas. Os estáticos " se tornam parte "do executável e os dinâmicos" se juntam " quando o executável é executado.

Existem vantagens e desvantagens em ambos os métodos e existem diferenças entre os sistemas operacionais. Mas como não perguntaste, vou acabar com isto aqui.
 226
Author: Artelius, 2014-01-22 22:13:56

As bibliotecas com ligações estáticas estão ligadas no momento da compilação. Bibliotecas ligadas dinamicamente são carregadas em tempo de execução. A ligação estática faz a parte da biblioteca entrar no seu executável. Dynamic linking only bakes in a reference to the library; the bits for the dynamic library exist elsewhere and could be swapped out later.

 32
Author: John D. Cook, 2008-11-22 23:13:41

Porque nenhum dos posts acima realmente mostram como {[14] } para estaticamente ligar algo e ver que você fez isso corretamente para que eu vou abordar esta questão:

UM programa C simples

#include <stdio.h>

int main(void)
{
    printf("This is a string\n");
    return 0;
}

Liga dinamicamente o programa C

gcc simpleprog.c -o simpleprog

E executar file no binário:

file simpleprog 
E isso mostrará que está dinamicamente ligado a algo como:

"simpleprog: executável LSB de 64 bits ELF, x86-64, versão 1 (SYSV), dinamicamente ligado (usa libs compartilhados), para GNU / Linux 2.6.26, BuildID [sha1]=0xf715572611a8b04f686809d90d1c0d75c6028f0f, não despojado "

Em vez disso, vamos estabelecer uma ligação estática com o programa desta vez.
gcc simpleprog.c -static -o simpleprog

Se correr um ficheiro neste binário com ligações estáticas irá mostrar:

file simpleprog 

"simpleprog: executável LSB de 64 bits ELF, x86-64, versão 1( GNU / Linux), estaticamente ligado, para o GNU / Linux 2.6.26, BuildID [sha1]=0x8c0b12250801c5a7c7434647b7dc65a644d6132b, não despojado"

E podes ver que é feliz tem ligações estáticas. Infelizmente, no entanto, nem todas as bibliotecas são simples de ligar estaticamente desta forma e podem exigir esforço estendido Usando libtool ou ligando o código objeto e bibliotecas C à mão.

Felizmente, muitas bibliotecas C embutidas como musloferecem opções de ligação estática para quase todas Se não todas das suas bibliotecas.

Agora strace o binário que você criou e você pode ver que não existem bibliotecas acessadas antes do programa começar:

strace ./simpleprog

Agora compare com a saída de strace no programa ligado dinamicamente e você verá que o strace da versão ligada estaticamente é muito mais curto!

 16
Author: , 2015-10-06 03:37:06

(Eu não sei C# mas é interessante ter um conceito de ligação estática para uma linguagem VM) {[[2]}

Ligação dinâmica envolve saber como encontrar uma funcionalidade necessária que só tem uma referência do seu programa. Você Busca por um pedaço de código no sistema de arquivos, rede ou cache de código compilado, combinando a referência, e então toma várias medidas para integrá-lo à imagem do seu programa na memória, como a relocalização. Estão todos prontos a tempo de execução. Ele pode ser feito manualmente ou pelo compilador. Existe a capacidade de atualizar com um risco de confusão (ou seja, DLL hell).

A ligação estática é feita no tempo de compilação que, você diz ao compilador onde estão todas as partes funcionais e instrui-o a integrá-las. Não há busca, não há ambiguidade, não há capacidade de atualização sem uma recompilação. Todas as suas dependências são fisicamente unas com a imagem do seu programa.

 2
Author: artificialidiot, 2008-11-22 23:49:15