
- •Статические и динамические библиотеки (сборка и использование)
- •Автоматизация сборки приложений с помощью make
- •Создание процессов, системные вызовы fork и exec(см.Файлик)
- •Процессы демоны, создание процессов демонов Демоны и потоки
- •Структуры данных процесса
- •Идентификационные данные процесса
- •Контекст процесса
- •Состояния процессов
- •Другие параметры процесса
- •Режимы выполнения процессов
- •Средства межпроцессорного взаимодействия
- •Методы межпроцессного взаимодействия
- •[Править]Реализации
- •Проблемы межпроцессного взаимодействия
- •Обмен информацией между процессами
- •Сигналы
- •Разделяемая память
- •Семафоры, системные вызовы для работы с семафорами
- •Семафоры
- •3.1. Использование семафоров
- •3.2. Создание множеств семафоров
- •3.3. Управление семафорами
- •3.3.1. Использование semctl
- •Очереди сообщений, системные вызовы для работы с очередями сообщений
- •2.1. Использование очередей сообщений
- •2.2. Создание очередей сообщений
- •2.2.1. Использование msgget
- •Разделяемая память, системные вызовы для работы с разделяемой памятью
- •4.1. Использование разделяемых сегментов памяти
- •4.2. Создание разделяемых сегментов памяти
- •4.3. Управление разделяемыми сегментами памяти
- •4.3.1. Использование shmctl
Статические и динамические библиотеки (сборка и использование)
1) Статическая библиотека - это такая библиотека, которая связывается (линкуется) с программой в момент компиляции оной. При этом объектный код библиотеки помещается в исполняемый файл программы. С этой точки зрения статическая библиотека похожа на исходный код программы, с которой она связывается, за исключением того, что библиотека компилируется "кем-то еще" и программист, использующий библиотеку, имеет дело исключительно только с результатом этой компиляции. В Linux, как правило, файл-статическая_библиотека имеет расширение ".a" 2) Статические библиотеки на языке C. Исходный код библиотеки: ###################### #include <stdio.h> extern int hello() { printf("Hello world! I'm static library\n"); return 0; }; ###################### Сохраните его в файле static.c Ключевое слово extern необходимо для того, чтобы функция была видна в программе. Теперь скомпилируем (! без линковки) библиотеку: gcc -c static.c -o static.o (на выходе имеем файл static.o, содержащий объектный код нашей библиотеки) ar rc libMY_STATIC.a static.o ar упаковывает несколько (! Это важно. Дело не ограничивается только одним объектным файлом) объектных файлов в одну статическую библиотеку. Статическая библиотека имеет расширение ".a", при этом ее название должно начинаться с "lib" (дань традиции). Параметры ar: r - предписывает заменять старые версии объектных файлов новыми - необходим для переупаковки библиотеки; c - создать статическую библиотеку, если та еще не существует. Проиндексируем функции внутри библиотеки для более быстрой линковки: ranlib libMY_STATIC.a Итак, мы получили статическую библиотеку libMY_STATIC.a. Теперь попытаемся использовать библиотеку в нашей программе: Исходный текст программы (C): ###################### #include <stdio.h> int main() { int x = hello(); printf("Return code: %d\n",x); return 0; } ###################### Сохраните его в файле program1.c Способы связывания библиотеки и программы: - Скомпилируем и слинкуем (в том числе с нашей библиотекой) нашу программу: gcc program1.c libMY_STATIC.a (предполагается, что в качестве аргумента gcc будут переданы полные пути (!) к вашим библиотекам) И запустим: ./a.out На выходе получим:
Hello world! I'm static library Return code: 0
Отлично! - Скомпилируйте с помощью команды: gcc program1.c -L. -lMY_STATIC -o a1.out Смысл аргументов: -L - путь к каталогу, содержащему наши библиотек (используйте "-L -L - название нашей библиотеки (это важно - название (!), а не имя файла - собственно, если библиотека имеет своим именем "libBLABLABLA.a", то ее названием будет "BLABLABLA" - т.е. имя без приставки "lib" и расширения ".a") (для нескольких библиотек используйте "-l -l ...") Запустите файл a1.out на выполнение и удостовертесь, что результаты те же, что и в предыдущем пункте. - Видоизменим предыдущий способ - уберем аргументы "-L": В начале проверим значение переменной LD_LIBRARY_PATH и содержимое файла /etc/ld.so.conf: echo $LD_LIBRARY_PATH ; cat /etc/ld.so.conf На экране появился некоторый список каталогов - это те каталоги, в которых система ищет библиотеки при их линковке с программой (еще к таким каталогам относятся: /lib /usr/lib . Поместите libMY_STATIC.a в один из этих каталогов: (Я, к примеру, засуну нашу библиотеку в каталог /usr/lib): su -c 'cp libMY_STATIC.a /usr/lib' (в Ubuntu - sudo cp libMY_STATIC.a /usr/lib) ldconfig (ldconfig обновляет кеш данных о библиотеках линковщика) Теперь скомпилируем и запустим нашу программу: gcc program1.c -lMY_STATIC -o a2.out ./a2.out Результат:
Hello world! I'm static library Return code: 0
1) Динамическая библиотека - библиотека, подключаемая к программе в момент выполнения. Это означает, что при создании библиотеки производится не только ее компиляция, но и линковка с другими, нужными ей, библиотеками (!). Динамические библиотеки полезны в случаях, если: - Важно не перекомпилировать всю программу, а только перекомпилировать ту часть, которая реализует определенные функции - тогда эти функции выносятся в динамическую библиотеку; - Важно использовать в программах на C библиотеки, подготовленные на C++ и при этом избежать лишних трудностей с линковкой программы; - Кроме того, динамические библиотеки позволяют экономить место на жестком диске и в оперативной памяти, если одна и таже библиотека используется несколькими программами. В Linux, обычно, динамические библиотеки имеют расширение ".so". 2) Подготовим исходный код динамической библиотеки (пример на C++). Исходный код динамической библиотеки по принципам создания ничем (!) не отличается от исходного кода статических библиотек. Здесь мы подготовим некоторый пример, который в дальнейшем будем использовать повсеместно во всей части 2. Итак, исходный код библиотеки (C++): ###################### #include <iostream> using namespace std; #include <dynamic.h> extern "C" int hello() { cout<<"Hello world!\n I'm function hello()"<<endl; return 0; } ###################### Сохраните приведенный код в файле dynamic.cpp. * Кстати, внутри динамической библиотеки вы можете описать следующие функции: void _init() - будет вызвана при инициализации динамической библиотеки (загрузки ее в память); void _fini() - будет вызвана при выгрузке из памяти динамической библиотеки. 3) Компиляция и линковка динамических библиотек. Давайте получим динамическую библиотеку: Получим файл с объектным кодом: g++ -fPIC -c dynamic.cpp -o dynamic.o (используйте gcc для программ на С и Assembler'е) Здесь: -fPIC - использовать относительную адресацию в переходах подпрограмм - во избежание конфликтов при динамическом связывании А теперь из объектного файла получим библиотеку: g++ -shared -olibdynamic.so dynamic.o (используйте gcc для программ на С и Assembler'е) libdynamic.so - имя результирующей библиотеки; -shared - предписывает создать динамическую (т.е. "разделяемую") библиотеку. * Именуйте динамические библиотеки следующим способом: libNAME.so Это традиция ;-) Итак, на выходе мы имеем libdynamic.so - нашу динамическую библиотеку. 4) Использование динамической библиотеки в программе на C/C++. - Связывание с библиотекой во время компиляции программы (C/C++): ------ Подготовим исходный код нашей программы: (С) ###################### int main() { int x = hello(); printf("Return code: %x\n",x); return 0; } ###################### Сохраните его в файле Dprogram1.c ИЛИ (С++) ###################### #include <stdio.h> extern "C" int hello(); int main() { int x = hello(); printf("Return code: %x\n",x); return 0; } ###################### Сохраните его в файле Dprogram1.cpp (единственное отличие, как вы можете заметить, в ключевом слове extern - см. часть 1 пункт 4) ------ Теперь добьемся того, чтобы система смогла найти нашу библиотеку. Поместим libdynamic.so в один из каталогов: из списка: echo $LD_LIBRARY_PATH /lib /usr/lib или из списка: cat /etc/ld.so.conf и выполните потом "ldconfig" ------ И, наконец, скомпилируем программу и слинкуем ее с библиотекой: gcc ИСХОДНИК -lИМЯ_БИБЛИОТЕКИ -o РЕЗУЛЬТИРУЮЩИЙ_БИНАРИК В нашем случае: gcc Dprogram1.c -L/home/amv/c/libs/ -ldynamic (используйте g++ для программы на C++) Запустим на исполнение полученный файл: ./a.out В итоге должно получится:
Hello world! I'm function hello() Return code: 0
- Связывание с библиотекой во время исполнения программы (C/C++): Разумеется, предыдущий пример неплох. Однако бывает необходимо подключать библиотеку во время выполнения программы. Для этого можно использовать функционал из заголовочного файла . Исходный код примера (C): ###################### #include <dlfcn.h> #include <stdio.h> int main() { void *handle = dlopen("libdynamic.so",RTLD_LAZY); int(*fun)(void) = dlsym(handle,"hello"); int x = (*fun)(); dlclose(handle); printf("Return code: %d\n",x); return 0; }; ###################### Сохраните его в файле Dprogram2.c В dlfcn.h определены следующие функции: void* dlopen("PATH_AND_NAME",FLAG) - загружает в память динамическую библиотеку с полным именем PATH_AND_NAME и возвращает ее описатель (HANDLE) (NULL в случае неудачи). FLAG - флаги, описанные в "man dlopen"; void* dlsym(HANDLE,"NAME") - возвращает указатель на функцию/переменную, импортируемую из библиотеки; int dlclose(HANDLE) - выгружает библиотеку из памяти; const char *dlerror() - получить сообщение о последней возникшей ошибке (NULL - если ошибок не произошло с момента последнего вызова dlerror). * Посмотрите на досуге вот этот перевод "man dlopen": Привет, OpenNET Выполняем: gcc -ldl Dprogram2.c (используйте g++ для программы на C++) Запустим на исполнение полученный файл: ./a.out В итоге должно получится:
Hello world! I'm function hello() Return code: 0
* Важно! Нет необходимости помещать библиотеку в один из специальных каталогов, модифицировать переменные окружения и выполнять "ldconfig" - Использование динамической библиотеки в программе на Python: Все предельно просто. ------ Поместим libdynamic.so в один из каталогов: из списка: echo $LD_LIBRARY_PATH /lib /usr/lib или из списка: cat /etc/ld.so.conf и выполните потом "ldconfig"