2012-12-18 17 views
5

Usiłuję zbudować program w C, który ma wiele dodatkowych funkcji, które zależą od różnych bibliotekach dzielonych.Wykrywanie możliwości biblioteki w czasie wykonywania w C

W naszym heterogenicznym klastrze obliczeniowym nie wszystkie z tych bibliotek dostępne (lub na bieżąco) na wszystkich systemach są.

Przykładami są symbole z nowszej glibc ([email protected]@GLIBC_2.6, [email protected]@GLIBC_2.6) lub całych współdzielonych bibliotek, które mogą być lub mogą nie być dostępne (libnuma, libR, libpbs).

wiem, że mogę używać libdl załadować symbole z dlopen i dlsym, ale robi to dla coraz większej liczby symboli (około 30 w tej chwili) jest uciążliwe w najlepsze.

O ile mi zrozumieć współdzielone biblioteki w systemie Linux są leniwi ładowane domyślnie, więc nie powinno być potrzebne symbolem dopóki nie zostanie właściwie wykorzystane.

Ale gdy próbuję sprawdzić, że wcześniej to się nie powiedzie na początku wykonywania:

#define _GNU_SOURCE 
#include <stdlib.h> 
#include <stdio.h> 
#include <stdint.h> 
#include <dlfcn.h> 
#include <sched.h> 

int main() { 

    void *lib_handle; 
    int (*fn)(void); 
    int x; 
    char *error; 

    lib_handle = dlopen("libc.so.6", RTLD_LAZY); 
    if (!lib_handle) 
    { 
     fprintf(stderr, "%s\n", dlerror()); 
     exit(1); 
    } 

    fn = dlsym(lib_handle, "sched_getcpu"); 
    if ((error = dlerror()) != NULL) 
    { 
     fprintf(stderr, "%s\n", error); 
     exit(1); 
    } 

    printf("%d\n", sched_getcpu()); 

    return 0; 
} 

na system kompilacji, który posiada wszystkie biblioteki:

$ icc test.c 
$ ./a.out 
10 

na innym systemie, który ma mniej ostatnia wersja GLIBC:

$ ./a.out 
./a.out: /lib64/libc.so.6: version `GLIBC_2.6' not found (required by ./a.out) 

Jeśli skomentuję linię, która faktycznie wywołuje sched_getcpu potem dostać zamiast w mniejszym systemie:

$ ./a.out 
/lib64/libc.so.6: undefined symbol: sched_getcpu 

Więc, czy jest jakiś sposób aby zmusić biblioteki tylko mają zostać załadowane na użyciu i mieć kontrole jak te przed blokami, które z nich korzystają?

+0

To może być bezpieczniejsze w dłuższej perspektywie, aby spróbować zrobić klaster odrobinę bardziej jednorodna. Alternatywnie najlepszym rozwiązaniem jest połączenie statyczne wszystkich plików wykonywalnych, które muszą działać na tych niekonsekwentnie obsługiwanych systemach, i mam nadzieję, że przynajmniej działają przyzwoicie zgodne jądra. Jeśli w klastrze działa BSD, szczególnie NetBSD byłoby to łatwe, o ile połączysz aplikację z najstarszą wersją systemu działającego w klastrze. –

+0

@ GregA.Woods To jest to, co powtarzam moim administratorom. Ale problem polega na tym, że jestem programistą. Muszę napisać kod i uruchomić go. Nie mam nawet dostępu administratora do klastra, więc nie jest to opcja. Jądra są wszystkim Linuksem, ale jest to mieszanka CentOS w różnych smakach na maszynach o małej mocy i RedHat na superkomputerach. –

+0

Następnie łączenie statyczne jest twoją najlepszą, a może jedyną opcją. Być może będziesz musiał zbudować własną maszynę do kompilacji, aby znaleźć wersję jądra o najmniejszym wspólnym mianowniku. W przypadku większości rzeczy nie jest to trudne. –

Odpowiedz

1

Nie z glibc. Jest to bezpieczne i działa tak, że nie będziesz strzelał sobie w stopę. Jeśli symbol GLIBC_2.6 nie został zdefiniowany i nie został wyświetlony, nawet jeśli nie było innych brakujących symboli, można uzyskać wyniki czyszczenia z glibc (uszkodzenie danych i awarie), ponieważ nie jest zgodny z wcześniejszymi wersjami.

Jeśli potrzebujesz kompatybilność na poziomie glibc, trzeba zbudować w stosunku do najniższego wspólnego wersji.

+0

OK, więc będę musiał ręcznie wczytać symbole glibc lub bezpośrednio użyć 'syscall'. W tej chwili jestem niekompatybilny z dwoma wymienionymi symbolami. A co z innymi bibliotekami? –

+0

@SergeyL. Inne biblioteki działają tak jak zwykle. Jeśli definicje podanych symboli są zgodne, będą działać. –