/* удалить любое состояние ошибки, которое еще не было прочитано */
dlerror();
p = dlsym(handle, "this_symbol");
if ((error = dlerror()) != NULL) {
/* обработка ошибки */
}
Так как функция dlsym()
возвращает void *
, вам необходимо использовать приведение типов, чтобы компилятор С не выдавал сообщений об ошибках. Если вы сохраняете указатель, возвращенный функцией dlsym()
, сохраните его в переменной того типа, который вы хотите использовать, и выполните приведение типа во время вызова функции dlsym()
. Не сохраняйте результат в переменной void *
; вам придется выполнять приведение типов каждый раз во время ее использования.
Функция dlclose()
закрывает библиотеку.
void * dlclose(void * handle);
Функция dlclose()
проверяет счетчик обращений, который увеличивался на единицу при каждом повторном вызове функции dlopen()
, и если он равен нулю, она закрывает библиотеку. Этот счетчик обращений позволяет библиотекам применять функции dlopen()
и dlclose()
для произвольных объектов, не беспокоясь о том, что код, в котором производится вызов, уже открыл какие-либо из этих объектов.
В главе 8 был представлен пример использования обычной разделяемой библиотеки. Библиотеку libhello.so
, которую нам удалось создать, можно загружать во время выполнения. Программа loadhello
загружает libhello.so
динамически и вызывает функцию print_hello
, которая находится в библиотеке.
Ниже показан код loadhello.с
.
1: /* loadhello.с */
2:
3: #include
4: #include
5: #include
6:
7: typedef void (*hello_function) (void);
8:
9: int main(void) {
10: void * library;
11: hello_function hello;
12: const char * error;
13:
14: library = dlopen("libhello.so", RTLD_LAZY);
15: if (library == NULL) {
16: fprintf (stderr, "He удается открыть libhello.so: %s\n",
17: dlerror());
18: exit(1);
19: }
20:
21: /* Хотя в данном случае мы знаем, что символ print_hello никогда
22: * не должен быть равен NULL, при поиске произвольных символов
23: * все происходит иначе. Поэтому вместо проверки результата функции dlsym()
24: * мы показываем пример проверки кода, возвращаемого функцией dlerror().
25: */
26: dlerror();
27: hello = dlsym(library, "print_hello");
28: error = dlerror();
29: if (error) {
30: fprintf(stderr, "He удается найти print_hello: %s\n", error);
31: exit(1);
32: }
33:
34: (*hello)();
35: dlclose(library);
36: return 0;
37: }
Глава 28
Идентификация и аутентификация пользователей
В модели безопасности Linux для идентификации пользователей и групп используются числа, однако люди отдают предпочтение именам. Имена, наряду с другой важной информацией, сохраняются в двух системных базах данных.
28.1. Преобразование идентификатора в имя
В результате выполнения команды ls -l
для вывода списка содержимого текущего каталога в третьей и четвертой колонках указываются идентификаторы (ID) пользователя и группы, к которой принадлежит каждый файл. Этот список выглядит примерно следующим образом.
drwxrwxr-x 5 christid christid 1024 Aug 15 02:30 christid
drwxr-xr-x 73 johnsonm root 4096 Jan 18 12:48 johnsonm
drwxr-xr-x 25 kim root 2048 Jan 12 21:13 kim
drwxrwsr-x 2 tytso tytso 1024 Jan 30 1996 tytso
Однако нигде в ядре не хранится строка christid
. Программа ls
осуществляет преобразование номеров, предоставленных ядром, в имена. Она получает номера из системного вызова stat()
и производит поиск имен в двух системных базах данных. Обычно эти базы данных хранятся в файлах /etc/passwd
и /etc/group
, хотя в некоторых системах информация может располагаться где-нибудь в сети или в каком-то другом нестандартном месте. Программистам не нужно беспокоиться о том, где хранится эта информация; библиотека С предлагает обобщённые функции, которые считывают конфигурационные файлы для определения места хранения этой информации, производят выборку информации и возвращают ее незаметно для вас.
Чтобы продемонстрировать, что программа ls
получает из ядра, выполним команду ls -ln
.
drwxrwxr-x 5 500 500 1024 Aug 15 02:30 christid
drwxr-xr-x 73 100 0 4096 Jan 18 12:48 johnsonm
drwxr-xr-x 25 101 0 2048 Jan 12 21:13 kim
drwxrwsr-x 2 1008 1008 1024 Jan 30 1996 tytso
Структура, представляющая элементы в /etc/passwd
(или эквивалентной базы данных системы), определена в .
struct passwd {
char * pw_name; /* Имя пользователя */
Читать дальше