5 Kasım 2019 Salı

dlopen metodu

Giriş
Bir shared object kütüphanesini yüklemek için kullanır. İmzası şöyle.
void * dlopen (const char *file, int mode)
mode olarak RTDL_LAZY, RTDL_NOW, RTDL_GLOBAL, RTDL_LOCAL seçeneklerinden birisi kullanılabilir. RTLD_NOAUTODEFER bayrağı Linux'ta mevcut değil.

Bu method dosyayı open() ile açar ve mmap() ile uygulamanın adres alanına dahil eder. Bu metod ile birlitek dlsym() kullanılır.

RTDL_GLOBAL Seçeneği
Açıklaması şöyle.
RTLD_GLOBAL makes the symbols of the loaded library available for use in resolving symbols for future dlopen calls, or dlsym calls on the global namespace (as opposed to a particular library). It does not redefine existing symbols or magically make unresolved ones in already-relocated code/data now resolve to the new definitions.
Örnek - RTDL_LAZY + RTDL_GLOBAL 
Şöyle yaparız. Burada C uygulaması olduğu için değişkenler en üstte tanımlı.
int main(void) {
  void *lib;
  zip_t *p_open(const char *, int, int *);
  void *p_close(zip_t*);
  int err;
  zip_t *myzip;

  lib = dlopen("libzip.so", RTLD_LAZY | RTLD_GLOBAL);
  if (lib == NULL)
    return 1;

  p_open = (zip_t(*)(const char *, int, int *))dlsym(lib, "zip_open");
  if (p_open == NULL)
    return 1;
  p_close = (void(*)(zip_t*))dlsym(lib, "zip_close");
  if (p_close == NULL)
    return 1;

  myzip = p_open("myzip.zip", ZIP_CREATE | ZIP_TRUNCATE, &err);
  if (myzip == NULL)
    return 1;

  p_close(myzip);
  return 0;
}
Örnek - RTDL_LAZY
Belirtilen .so dosyasının bağımlı olduğu diğer .so dosyaları lazy olarak yüklemek ve bağımlılıkları global sembol tablosuna eklemek için şöyle yaparız.
void* handle = ::dlopen("mylib.so", RTLD_LAZY);
Örnek - RTDL_LOCAL + RTDL_LAZY
Belirtilen .so dosyasının bağımlı olduğu diğer .so dosyaları lazy olarak yüklemek ve bağımlılıkları local sembol tablosuna eklemek için şöyle yaparız.
void *handle = dlopen("mylib.so", RTLD_LOCAL | RTLD_LAZY);
Örnek
Yükleyeceğimiz .so dosyasının bağımlılığı  pthread.so olsun. Ancak kütüphanemiz bu bağımlılığı belirtecek şekilde linklenmemiş olsun. Bu durumda .so dosyasını yüklemeye çalışırsak şu hatayı alırız.
dlopen failed: /usr/lib/libTextSearch.so: undefined symbol: pthread_create
RUN FINISHED; exit value 1; real time: 0ms; user: 0ms; system: 0ms
Önce bağımlılığı yüklemek için şöyle yaparız.
void* handlePthread = dlopen("libpthread.so.0", RTLD_GLOBAL | RTLD_LAZY);
if(!handlePthread ){
    fprintf(stderr, "dlopen failed: %s\n", dlerror());
}
Örnek
Kendi uygulamamızı elde etmek için şöyle yaparız. Aynı şey dlsym (RTDL_MAIN_ONLY,...) ile de yapılabilir.
void* handle = dlopen (NULL, RTLD_LAZY);
Hata Kontrolü
Örnek
Şöyle yaparız.
void* handle = dlopen("libTextSearch.so", RTLD_LAZY);
if(!handle){
  fprintf(stderr, "dlopen failed: %s\n", dlerror());
}
Örnek
Eğer hata varsa şöyle yaparız.
if (!handle) {
  throw std::runtime_error(::dlerror());
}

Hiç yorum yok:

Yorum Gönder