Hlavní navigace

Programování pod Linuxem pro všechny (5)

Jakub Matys

V dnešním dílu proberu, jak jsem minule slíbil, použití nestandardních adresářů pro uložení dynamických knihoven (pomocí proměnné LD_LIBRARY_PATH a přeložení programu s volbou -Wl, -rpath) a zavádění dynamických knihoven za běhu programu.

V diskusi k minulému dílu jste se zmiňovali, že byste chtěli nějaké informace o libtool, rozhodl jsem se tedy tomuto nástroji věnovat příští díl (nebo několik dílů).

Nestandardní knihovní adresáře

Když spojíte váš program s dynamickou knihovnou, vloží spojovací program do spustitelného kódu pouze její jméno. Když se program spustí, jsou sdílené knihovny zaváděny z adresářů /lib a /usr/lib. Pokud není daná knihovna v některém z adresářů, systém odmítne spustit program.

Budete-li chtít použít nestandardní adresáře, máte na výběr ze dvou řešení. Prvním z nich je, že při spojování programu použijete volby-Wl, -rpath

# gcc -o egg egg.c -L. -ltest -Wl, -rpath, /usr/local/lib 

Volba -Wl ,option slouží k předání dodatečných argumentů linkovacímu programu. Nyní spustitelný kód obsahuje i adresář, kde má hledat sdílenou knihovnu.

Pokud ovšem nemůžete program znovu přeložit (např. je distribuován v binární formě), můžete použít systémovou proměnnou LD_LIBRARY_PATH. Podobně jako proměnná PATH obsahuje seznam adresářů oddělených dvojtečkou. Pokud si například do proměnné uložíte /usr/local/lib, bude se tento adresář prohledávat před adresáři /lib a /usr/lib. Dále je důležité vědět, že se při dalším spojování programů budou prohledávat také adresáře uvedené v proměnné.

Zavádění dynamických knihoven

Někdy je nutné zavést jistý kód do paměti až v době realizace programu. Příkladem může být třeba webový prohlížeč. Do většiny prohlížečů je možné zavádět moduly, čímž rozšiřujete funkce programu.

Pro zavádění dynamických knihoven do paměti je možné použít funkci dlopen(), funkční prototyp funkce je

void *dlopen (const char *filename, int flag);

Drhuhý parametr je přepínač, který nastavuje způsob vazby symbolů ve sdílené knihovně. Nejčastěji se používá volba RTLD_LAZY (další volby viz # man 3 dlopen). Návratový kód se používá jako odkaz na sdílenou knihovnu. Hodnotu návratového kódu můžete předat funkcidlsym(), a obdržíte tak adresu funkce, jež byla zavedena spolu s dynamickou knihovnou. Funkční prototyp funkce je

void *dlsym(void *handle, char *symbol);

handle je zmíněný odkaz na knihovnu, symbol je název funkce, jejíž adresu chcete předat jako návratový kód. Funkce dlsym může být použita také k získání ukazatele na statickou proměnnou ve sdílené knihovně.

Obě funkce vracejí hodnotu NULL, pokud se ukončí s chybou. V takovém případě můžete volat funkci dlerror() (bez parametrů), a získat tak textový popis příčiny.

int dlclose (void *handle);

Tato funkce se používá k uvolnění knihovny z paměti.

Pokud chcete využívat uvedených funkcí, musíte vložit do vašeho zdrojového souboru odkaz na hlavičkový soubor dlfcn.h a přeložit program s volbou -ldl. Uvedu zde příklad z manuálových stránek. Program vypočítá cosinus dvou funkcí cos() z dynamicky zavedené knihovny libm.so:

#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
  void *handle;
  double (*cosine)(double);
  char *error;

  handle = dlopen ("/lib/libm.so", RTLD_LAZY);
  if (!handle) {
    fputs (dlerror(), stderr);
    exit(1);
  }

  cosine = dlsym(handle, "cos");
  if ((error = dlerror()) != NULL) {
    fprintf (stderr, "%s\n", error);
    exit(1);
  }

  printf ("%f\n", (*cosine)(2.0));
  dlclose(handle);
}

To je dnes vše, doufám, že se vám nově získané informace budou hodit. A jak jsem se na začátku článku zmínil, příští díl se budeme věnovat libtool.

Našli jste v článku chybu?
23. 2. 2004 7:48
Tomas Dean (neregistrovaný)

Mozna by se hodil kratky popis funkce strip, plus informace o tom, proc mi nektere stripnute binarky (hlavne .a knihovny) nechteji fungovat, a jak udelat, abych je mohl stripnout a pritom aby fungovaly :)

22. 2. 2004 21:40
Petr Baudis (neregistrovaný)

Kdybych ja mel napsat clanky o vsem, o cem bych chtel... ;-)