Esta questão não é específica para o Solaris.
Quando você instala uma biblioteca compartilhada (ou um software que fornece uma biblioteca compartilhada), você obtém três arquivos, todos com aparência semelhante, mas com finalidades diferentes.
-
libfoo.so.1.0.0
- Este é o arquivo de dados (regular). Ele contém a biblioteca em si. Você poderia ter vários destes, com diferentes versões. Dentro deste arquivo, há um campo ELF chamado SONAME , que é definido comolibfoo.so.1
. No Linux, executeobjdump -p libfoo.so.1.0.0 | grep SONAME
para descobrir. -
libfoo.so
→libfoo.so.1.0.0
- Este é um link simbólico que é usado ao compilar o software contra a libfoo. Quando você especifica-lfoo
para o vinculador, ele procurará exatamentelibfoo.so
. Normalmente,libfoo.so
nunca é um arquivo regular, é sempre um link simbólico que aponta para a versão do libfoo que você deseja usar para vincular. Em um ambiente de criação complexo, você pode ter várias versões da biblioteca e usar esse link simbólico para escolher, em relação à versão que deseja vincular. -
libfoo.so.1
→libfoo.so.1.0.0
- Este também é um symlink, que é usado quando você executa binários que precisam de sua biblioteca. Lembre-se do campo SONAME que mencionei? Quando você vincula um binário ao libfoo, o binário registrará o SONAME da biblioteca e o utilizará em tempo de execução.
Esta configuração permite que você tenha várias versões da mesma biblioteca instaladas lado a lado. Binários diferentes podem requerer versões diferentes da biblioteca, e cada binário encontrará a versão correta da biblioteca. Geralmente, o SONAME da biblioteca é alterado pelo upstream quando há uma alteração de API incompatível com versões anteriores. Todos os binários antigos ainda usam a API antiga, enquanto binários recém-vinculados usam a nova.
Alguns projetos de empacotamento, o Debian seria um exemplo, use pacote diferente nomes para diferentes versões de uma biblioteca. Isso permite que você instale e desinstale cada versão da biblioteca compartilhada de forma independente.
Existem alguns casos de borda. Por exemplo, dependências entre bibliotecas compartilhadas podem levar a duas versões sendo puxadas ao mesmo tempo. Considere:
foo → libbar.so.1, libbaz.so.1
libbar.so.1 → libbaz.so.1
Imagine que instalemos uma nova versão do libbaz e recompile o foo. Agora temos:
foo → libbar.so.1, libbaz.so.2
libbar.so.1 → libbaz.so.1
No tempo de execução, foo carregará libbaz.so.2
e libbar.so.1
, e libbar.so.1
carregará libbaz.so.1
. Veja o problema? Duas versões do libbaz são carregadas ao mesmo tempo. Não tenho certeza qual é a consequência exata em termos do layout do código na memória, mas na prática isso resulta em falhas.