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ą?
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. –
@ 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. –
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. –