Como os números SO (objeto compartilhado) funcionam?

123

Estou ciente de que objetos compartilhados no Linux usam "so numbers", ou seja, que versões diferentes 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 a "DLL Hell" no Windows). Gostaria de saber como isso funciona na prática? Muitas vezes, vejo que example.soé de fato um link simbólico para example.so.2onde .2está a versão mais recente. Como, então, um aplicativo, dependendo de uma versão mais antiga, example.soidentifica-o corretamente? Existem regras sobre quais números se deve usar? Ou isso é simplesmente uma convenção? É o caso de que, diferentemente 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 é vinculado à versão mais antiga automaticamente ao compilar a partir da origem?

Eu suspeito que isso esteja relacionado, ldconfigmas não sei como.

tshepang
fonte

Respostas:

87

Os próprios binários sabem de qual versão de uma biblioteca compartilhada eles dependem e solicitam-na especificamente. Você pode usar lddpara mostrar as dependências; meu para lssã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 libpthread.so.0, por exemplo , não apenas libpthread.so.


O motivo do link simbólico é para o vinculador. Quando você deseja vincular libpthread.sodiretamente, dá gcca bandeira -lpthreade ela adiciona o libprefixo e o .sosufixo automaticamente. Você não pode dizer para adicionar o .so.0sufixo, portanto o link simbólico aponta para a versão mais recente da lib para facilitar esse

Michael Mrozek
fonte
O sinal de igual "= ls" não deve estar presente. Basta usar "ldd ls"
bmacnaughton
1
@bmacnaughton Isso provavelmente causará um erro, pois lddrequer o caminho completo para o executável. =lsfaz isso em zsh, mas eu mudei uma vez que nem todo mundo usa essa casca
Michael Mrozek
Interessante. Estou executando o bash no Ubuntu e parece funcionar sem o caminho completo. Obrigado pela explicação - eu não uso o zsh.
precisa saber é o seguinte
60

Os números nas bibliotecas compartilhadas são convenção usada 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. O 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 alterados). Normalmente, o MINOR é incrementado para lançamentos de correções 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

miguel.de.icaza
fonte
Olá Miguel, obrigado por isso, pena que não posso aceitar duas respostas, porque isso complementa bem o acima. +1 de mim, excelente link também, obrigado novamente!
4
Isso é quase correto, mas na verdade é libFOO.so.MAJOR.MINOR(assim não no final)
JonnyJD
6
Esta resposta está tão errada . Primeiro, os números que você vê não têm nada a ver com a API, são puramente ABI. Segundo, a convenção aqui não é de versão semântica, como você sugere. Em vez disso, é uma convenção libtool que possui a boa propriedade de mapear para um número de versão de biblioteca única que o ld.so pode comparar (consulte gnu.org/software/libtool/manual/html_node/… para obter mais informações)
NewbiZ
23

As bibliotecas compartilhadas devem ter versão de acordo com o seguinte esquema:

blah.so.X.Y.Z

Onde

  • X = versão ABI incompatível com versões anteriores
  • Y = liberação ABI compatível com versões anteriores
  • Z = Apenas alterações internas - nenhuma alteração na ABI

Normalmente, você vê apenas o primeiro dígito como hello.so.1porque o primeiro dígito é a única coisa necessária para identificar a "versão" da biblioteca, pois todos os outros dígitos são compatíveis com versões anteriores.

ldconfigmanté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 é criado para algo como o Red Hat, as bibliotecas compartilhadas chamadas no binário serão pesquisadas e adicionadas como dependências do pacote no tempo de criação do RPM. Portanto, quando você instala o pacote, o instalador verifica se está ou não hello.so.1instalado no sistema, verificando ldconfig.

Você pode ver as dependências de um pacote fazendo algo como:

rpm -qpR hello.rpm

Esse sistema (ao contrário do Windows) permite que várias versões hello.sosejam instaladas em um sistema e sejam usadas por diferentes aplicativos ao mesmo tempo.

ascotan
fonte
Eu acho que essa é a melhor resposta.
Kemin Zhou #
1
As bibliotecas compartilhadas devem ser versionadas de acordo com o seguinte esquema (…) - Você poderia fornecer referência para esta declaração?
Piotr Dobrogost 19/03
19

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 é primeiro vinculada a um objeto compartilhado pelo processo de construção. Na verdade, esse SONAME é o que um vinculador armazena em um executável, dependendo do objeto compartilhado que está vinculado a ele. Normalmente, o SONAME está na forma de libNAME.so.MAJOR e é alterado a qualquer momento que a biblioteca se torna incompatível com os executáveis ​​existentes vinculados a ele e as duas versões principais da biblioteca podem ser mantidas instaladas conforme necessário (embora apenas um seja apontado 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 é aumentado 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 paraScripts para Linux, GNU GCC, ld, version e o formato binário ELF - Como funciona?

penguin359
fonte