Biblioteca compartilhada

Uma biblioteca compartilhada ou objeto compartilhado é um arquivo de computador que contém código executável projetado para ser usado por vários programas de computador ou outras bibliotecas em tempo de execução , com uma única cópia do código executável da biblioteca na memória. Isso difere de uma biblioteca estática , cujo código é copiado para o arquivo de imagem executável do programa quando o vinculador constrói esse arquivo, de modo que cada programa tenha sua própria cópia desse código na memória.

Ao executar um programa que usa uma biblioteca compartilhada, o sistema operacional carrega a biblioteca compartilhada de um arquivo (diferente do arquivo executável do programa) na memória em tempo de carregamento ou tempo de execução .

A maioria dos sistemas operacionais modernos usa o mesmo formato para bibliotecas compartilhadas e arquivos executáveis. [NB 1] Isso oferece duas vantagens principais: primeiro, requer apenas um carregador (construir e manter um único carregador considera-se que vale a pena qualquer complexidade adicional) [ carece de fontes ] . Em segundo lugar, permite que um arquivo executável seja usado como uma biblioteca compartilhada (se tiver uma tabela de símbolos ). Os exemplos incluem Unix ELF e Mach-O e Windows PE .

Em alguns ambientes mais antigos, como Windows de 16 bits ou MPE para HP 3000 , apenas dados baseados em pilha (locais) eram permitidos no código da biblioteca compartilhada ou outras restrições significativas eram impostas ao código da biblioteca compartilhada.

Compartilhamento de memória

O código da biblioteca pode ser compartilhado na memória por vários processos e no disco. Se a memória virtual for usada, os processos executariam a mesma página física de RAM mapeada nos diferentes espaços de endereço dos processos. Isto tem vantagens. Por exemplo, no sistema OpenStep , os aplicativos geralmente tinham apenas algumas centenas de kilobytes de tamanho e eram carregados rapidamente; a maior parte de seu código estava localizada em bibliotecas que já haviam sido carregadas para outros fins pelo sistema operacional. [ carece de fontes ]

Os programas podem realizar o compartilhamento de RAM usando código independente de posição , como no Unix , o que leva a uma arquitetura complexa, mas flexível, ou usando endereços virtuais comuns, como no Windows e no OS/2 . Esses sistemas garantem, por diversos meios, como pré-mapeamento do espaço de endereçamento e reserva de slots para cada biblioteca compartilhada, que o código tenha alta probabilidade de ser compartilhado. Uma terceira alternativa é o armazenamento de nível único , usado pelo IBM System/38 e seus sucessores. Isso permite código dependente de posição, mas não impõe restrições significativas sobre onde o código pode ser colocado ou como pode ser compartilhado.

Em alguns casos, versões diferentes de bibliotecas compartilhadas podem causar problemas, especialmente quando bibliotecas de versões diferentes têm o mesmo nome de arquivo e diferentes aplicativos instalados em um sistema exigem, cada um, uma versão específica. Esse cenário é conhecido como DLL hell , em homenagem ao arquivo DLL do Windows e do OS/2 . A maioria dos sistemas operacionais modernos posteriores a 2001 possuem métodos de limpeza para eliminar tais situações ou usam bibliotecas "privadas" específicas de aplicativos. [1]

Vinculação dinâmica

A vinculação dinâmica ou ligação tardia é a vinculação executada enquanto um programa está sendo carregado ( tempo de carregamento ) ou executado ( tempo de execução ), e não quando o arquivo executável é criado. Uma biblioteca vinculada dinamicamente ( biblioteca de vínculo dinâmico , ou DLL, no Windows e OS/2 ; imagem compartilhável no OpenVMS ; [2] objeto compartilhado dinâmico, ou DSO, em sistemas do tipo Unix ) é uma biblioteca destinada à vinculação dinâmica. Apenas uma quantidade mínima de trabalho é realizada pelo vinculador quando o arquivo executável é criado; ele registra apenas quais rotinas de biblioteca o programa precisa e os nomes ou números de índice das rotinas na biblioteca. A maior parte do trabalho de vinculação é feita no momento em que o aplicativo é carregado (tempo de carregamento) ou durante a execução (tempo de execução). Normalmente, o programa de vinculação necessário, chamado de "vinculador dinâmico" ou "carregador de vinculação", é na verdade parte do sistema operacional subjacente . (No entanto, é possível, e não excessivamente difícil, escrever um programa que utilize vinculação dinâmica e inclua seu próprio vinculador dinâmico, mesmo para um sistema operacional que não forneça suporte para vinculação dinâmica.)

Os programadores desenvolveram originalmente a ligação dinâmica no sistema operacional Multics , a partir de 1964, e no MTS ( Michigan Terminal System ), construído no final da década de 1960. [3]

Otimizações

Como as bibliotecas compartilhadas na maioria dos sistemas não mudam com frequência, os sistemas podem calcular um endereço de carregamento provável para cada biblioteca compartilhada no sistema antes que ela seja necessária e armazenar essas informações nas bibliotecas e nos executáveis. Se cada biblioteca compartilhada carregada tiver passado por esse processo, cada uma será carregada em seu endereço predeterminado, o que acelera o processo de vinculação dinâmica. Essa otimização é conhecida como pré-vinculação ou pré-vinculação no macOS e no Linux, respectivamente. O IBM z/VM usa uma técnica semelhante, chamada "Discontinuous Saved Segments" (DCSS). [4] As desvantagens desta técnica incluem o tempo necessário para pré-calcular esses endereços toda vez que as bibliotecas compartilhadas mudam, a incapacidade de usar a randomização do layout do espaço de endereço e a exigência de espaço de endereço virtual suficiente para uso (um problema que será aliviado pelo adoção de arquiteturas de 64 bits , pelo menos por enquanto).

Localizando bibliotecas em tempo de execução

Os carregadores para bibliotecas compartilhadas variam amplamente em funcionalidade. Alguns dependem do executável que armazena caminhos explícitos para as bibliotecas. Qualquer alteração na nomenclatura da biblioteca ou no layout do sistema de arquivos causará falha nesses sistemas. Mais comumente, apenas o nome da biblioteca (e não o caminho) é armazenado no executável, com o sistema operacional fornecendo um método para localizar a biblioteca no disco, com base em algum algoritmo.

Se uma biblioteca compartilhada da qual um executável depende for excluída, movida ou renomeada, ou se uma versão incompatível da biblioteca for copiada para um local anterior na pesquisa, o executável não será carregado. Isso é chamado de inferno de dependência , existente em muitas plataformas. A (infame) variante do Windows é comumente conhecida como DLL hell . Este problema não pode ocorrer se cada versão de cada biblioteca for identificada exclusivamente e cada programa fizer referência a bibliotecas apenas pelos seus identificadores exclusivos completos. Os problemas do "inferno de DLL" com versões anteriores do Windows surgiram do uso apenas de nomes de bibliotecas, que não tinham garantia de serem exclusivos, para resolver links dinâmicos em programas. (Para evitar o "inferno das DLL", as versões posteriores do Windows dependem em grande parte de opções para programas instalarem DLLs privadas - essencialmente uma retirada parcial do uso de bibliotecas compartilhadas - junto com mecanismos para evitar a substituição de DLLs de sistema compartilhado por versões anteriores delas. )

Microsoft Windows

O Microsoft Windows verifica o registro para determinar o local adequado para carregar DLLs que implementam objetos COM , mas para outras DLLs ele verificará os diretórios em uma ordem definida. Primeiro, o Windows verifica o diretório onde carregou o programa ( DLL privada [1] ); quaisquer diretórios definidos chamando a SetDllDirectory()função; os diretórios System32, System e Windows; então o diretório de trabalho atual; e finalmente os diretórios especificados pela variável de ambiente PATH . [5] Aplicativos escritos para o .NET Framework (desde 2002), também verificam o Global Assembly Cache como o armazenamento principal de arquivos DLL compartilhados para remover o problema de DLL hell .

OpenStep

OpenStep usou um sistema mais flexível, coletando uma lista de bibliotecas de vários locais conhecidos (semelhante ao conceito PATH) quando o sistema é iniciado pela primeira vez. A movimentação de bibliotecas não causa nenhum problema, embora os usuários incorram em um custo de tempo ao iniciar o sistema pela primeira vez.

Sistemas tipo Unix

A maioria dos sistemas do tipo Unix tem um "caminho de pesquisa" especificando diretórios do sistema de arquivos nos quais procurar bibliotecas dinâmicas. Alguns sistemas especificam o caminho padrão em um arquivo de configuração , outros o codificam no carregador dinâmico. Alguns formatos de arquivo executável podem especificar diretórios adicionais nos quais pesquisar bibliotecas para um programa específico. Isso geralmente pode ser substituído por uma variável de ambiente , embora esteja desabilitado para programas setuid e setgid, para que um usuário não possa forçar tal programa a executar código arbitrário com permissões de root. Os desenvolvedores de bibliotecas são incentivados a colocar suas bibliotecas dinâmicas em locais no caminho de pesquisa padrão. Por outro lado, isso pode tornar problemática a instalação de novas bibliotecas, e esses locais "conhecidos" rapidamente se tornam o lar de um número crescente de arquivos de biblioteca, tornando o gerenciamento mais complexo.

Carregamento dinâmico

O carregamento dinâmico, um subconjunto de vinculação dinâmica, envolve o carregamento e descarregamento de uma biblioteca vinculada dinamicamente em tempo de execução , mediante solicitação. Tal pedido pode ser feito de forma implícita ou explícita. Solicitações implícitas são feitas quando um compilador ou vinculador estático adiciona referências de biblioteca que incluem caminhos de arquivos ou simplesmente nomes de arquivos. [ citação necessária ] Solicitações explícitas são feitas quando os aplicativos fazem chamadas diretas para a API de um sistema operacional.

A maioria dos sistemas operacionais que suportam bibliotecas vinculadas dinamicamente também suportam o carregamento dinâmico de tais bibliotecas por meio de uma API de vinculador em tempo de execução . Por exemplo, o Microsoft Windows usa as funções API , e com Microsoft Dynamic Link Libraries ; Sistemas baseados em POSIX , incluindo a maioria dos sistemas UNIX e semelhantes a UNIX, usam , e . Alguns sistemas de desenvolvimento automatizam esse processo. LoadLibraryLoadLibraryExFreeLibraryGetProcAddressdlopendlclosedlsym

Notas

  1. ^ Alguns sistemas mais antigos, por exemplo, Burroughs MCP , Multics , também possuem um formato único

Leitura adicional

  • Como escrever bibliotecas compartilhadas por Ulrich Drepper (com muitas informações básicas)

Referências

  1. ^ Anderson, Rick (11/01/2000). "O fim do inferno das DLL" . microsoft. com. Arquivado do original em 05/06/2001 . Recuperado em 15/01/2012 . DLLs privadas são DLLs instaladas com um aplicativo específico e usadas somente por esse aplicativo.
  2. ^ "Manual do utilitário VSI OpenVMS Linker" (PDF) . VSI. Agosto de 2019 . Recuperado em 31/01/2021 .
  3. ^ “Uma História do MTS” . Resumo de tecnologia da informação . 5 (5).
  4. ^ Corporação IBM (2011). Planejamento e Administração de Segmentos Salvos (PDF) . Recuperado em 29 de janeiro de 2022 .
  5. ^ "Ordem de pesquisa da biblioteca de link dinâmico" . Biblioteca da Rede de Desenvolvedores Microsoft . Microsoft. 06/03/2012. Arquivado do original em 9 de maio de 2012 . Recuperado em 20/05/2012 .
Obtido em "https://en.wikipedia.org/w/index.php?title=Shared_library&oldid=1204526998"