%3F.png)
Estou ciente de que objetos compartilhados no Linux usam "so numbers", ou seja, diferentes versões de um objeto compartilhado recebem extensões diferentes, por exemplo:
example.so.1
example.so.2
Entendo que a idéia é ter dois arquivos distintos, de modo que duas versões de uma biblioteca possam existir em um sistema (em oposição ao "DLL Hell" no Windows). Gostaria de saber como isso funciona na prática? Freqüentemente, vejo que example.so
é na verdade um link simbólico para example.so.2
onde .2
está a versão mais recente. Como então um aplicativo que depende de uma versão mais antiga example.so
o identifica corretamente? Existem regras sobre quais números devem ser usados? Ou isso é simplesmente uma convenção? Será que, ao contrário do Windows, onde os binários de software são transferidos entre sistemas, se um sistema tiver uma versão mais recente de um objeto compartilhado, ele será vinculado automaticamente à versão mais antiga ao compilar a partir da fonte?
Suspeito que isso esteja relacionado, ldconfig
mas não sei como.
Responder1
Os próprios binários sabem de qual versão de uma biblioteca compartilhada eles dependem e a solicitam especificamente. Você pode usar ldd
para mostrar as dependências; os meus ls
são:
$ ldd /bin/ls
linux-gate.so.1 => (0xb784e000)
librt.so.1 => /lib/librt.so.1 (0xb782c000)
libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
libc.so.6 => /lib/libc.so.6 (0xb76dc000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
/lib/ld-linux.so.2 (0xb784f000)
libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)
Como você pode ver, aponta para, por exemplo libpthread.so.0
, não apenas libpthread.so
.
A razão do link simbólico é para o vinculador. Quando você deseja vincular libpthread.so
diretamente, você fornece gcc
o sinalizador -lpthread
e ele adiciona o lib
prefixo e .so
o sufixo automaticamente. Você não pode dizer para adicionar o .so.0
sufixo, então o link simbólico aponta para a versão mais recente da lib para facilitar isso
Responder2
Os números nas bibliotecas compartilhadas são convenções usadas no Linux para identificar a API de uma biblioteca. Normalmente o formato é:
libFOO.so.MAJOR.MINOR
E como você notou, geralmente há um link simbólico de libFOO.so para libFOO.so.MAJOR.MINOR. ldconfig é responsável por atualizar este link para a versão mais recente.
O MAJOR normalmente é incrementado quando a API é alterada (novos pontos de entrada são removidos ou os parâmetros ou tipos são alterados). O MINOR normalmente é incrementado para lançamentos de correção de bugs ou quando novas APIs são introduzidas sem quebrar as APIs existentes.
Uma discussão mais extensa pode ser encontrada aqui:Dissecando bibliotecas compartilhadas
Responder3
As bibliotecas compartilhadas devem ser versionadas de acordo com o seguinte esquema:
blah.so.X.Y.Z
onde
- X = versão ABI incompatível com versões anteriores
- Y = versão ABI compatível com versões anteriores
- Z = Somente alterações internas - nenhuma alteração na ABI
Normalmente você vê apenas o primeiro dígito hello.so.1
porque o primeiro dígito é a única coisa necessária para identificar a "versão" da biblioteca, já que todos os outros dígitos são compatíveis com versões anteriores.
ldconfig
mantém uma tabela de quais bibliotecas compartilhadas estão disponíveis em um sistema e onde existe o caminho para essa biblioteca. Você pode verificar isso executando:
ldconfig -p
Quando um pacote é compilado para algo como o Red Hat, as bibliotecas compartilhadas chamadas no binário serão pesquisadas e adicionadas como dependências do pacote no momento da compilação do RPM. Portanto, quando você for instalar o pacote, o instalador irá verificar se está ou não hello.so.1
instalado no sistema marcando ldconfig
.
Você pode ver as dependências de um pacote fazendo algo como:
rpm -qpR hello.rpm
Este sistema (ao contrário do Windows) permite que várias versões do hello.so
sejam instaladas em um sistema e usadas por diferentes aplicativos ao mesmo tempo.
Responder4
libNAME.so é o nome do arquivo usado pelo compilador/vinculador ao procurar pela primeira vez uma biblioteca especificada por -lNAME. Dentro de um arquivo de biblioteca compartilhada há um campo chamado SONAME. Este campo é definido quando a própria biblioteca é vinculada pela primeira vez a um objeto compartilhado (so) pelo processo de construção. Este SONAME é na verdade o que um vinculador armazena em um executável, dependendo do objeto compartilhado que está vinculado a ele. Normalmente o SONAME está no formato libNAME.so.MAJOR e é alterado sempre que a biblioteca se torna incompatível com os executáveis existentes vinculados a ela e ambas as versões principais da biblioteca podem ser mantidas instaladas conforme necessário (embora apenas uma seja apontada para desenvolvimento como libNAME.so) Além disso, para oferecer suporte à atualização fácil entre versões secundárias de uma biblioteca, libNAME.so.MAJOR normalmente é um link para um arquivo como libNAME.so.MAJOR.MINOR. Uma nova versão secundária pode ser instalada e, uma vez concluída, o link para a versão secundária antiga é alterado para apontar para a nova versão secundária, atualizando imediatamente todas as novas execuções para usar a biblioteca atualizada. Além disso, veja minha resposta paraLinux, GNU GCC, ld, scripts de versão e formato binário ELF - Como funciona?