Библиотека сайта rus-linux.net
Цилюрик О.И. Linux-инструменты для Windows-программистов | ||
Назад | Компиляция и сборка приложений | Вперед |
Данные в динамической библиотеке
До сих пор мы говорили только о функциях в библиотеке, вызываемых из кода приложения. А что, если библиотека содержит специфические данные, или даже модифицируются по ходу выполнения приложения? Сделаем библиотеку и соответствующую ей задачу, которые ответят нам на этот вопрос. Сначала смотрим код библиотеки:
lib.h : #define BUF_SIZE 200 void put_new_string( const char *s ); void get_new_string( char *s ); lib.c : #include <string.h> #include "lib.h" static char buffer[ BUF_SIZE + 1 ] = "initial buffer state!\n"; void put_new_string( const char *s ) { strcpy( buffer, s ); } void get_new_string( char *s ) { strcpy( s, buffer ); }
Вот, собственно, и вся библиотека: она экспортирует два имени, но функция
put_new_string()
изменяет содержимое внутреннего статического (невидимого внаружу)
буфера buffer
. И соответствующий пользовательский процесс, который на каждом
прохождении цикла индицирует значение, считанное им библиотечным вызовом get_new_string()
,
после чего обновляет по put_new_string()
это содержимое считанной с консоли строкой:
prog.c : #include "lib.h" #include <stdio.h> #include <stdlib.h> #include <time.h> void put( char* msg ) { time_t t; time( &t ); struct tm *m = localtime( &t ); printf( "%02d:%02d :\t%s", m->tm_min, m->tm_sec, msg ); } int main( int argc, char *argv[] ) { char buffer[ BUF_SIZE + 1 ] = ""; while( 1 ) { get_new_string( buffer ); put( buffer ); fprintf( stdout, "> " ); fflush( stdout ); fgets( buffer, sizeof( buffer ), stdin ); put( buffer ); put_new_string( buffer ); printf( "--------------------------\n" ); } }
Для ясности — сценарий и процесс сборки:
Makefile : LSRC = lib LNAME = new LIB = lib$(LNAME) PROG = prog all: $(LIB) $(PROG) $(LIB): $(LSRC).c $(LSRC).h gcc -c -fpic -fPIC -shared $(LSRC).c -o $(LSRC).o gcc -shared -o $(LIB).so $(LSRC).o rm -f $(LSRC).o $(PROG): $(PROG).c $(LIB) gcc $< -Bdynamic -L./ -l$(LNAME) -o $@ $ make gcc -c -fpic -fPIC -shared lib.c -o lib.o gcc -shared -o libnew.so lib.o rm -f lib.o gcc prog.c -Bdynamic -L./ -lnew -o prog $ ls lib.c lib.h libnew.so Makefile prog prog.c
А теперь выполняем c двух различных терминалов два
независимых экземпляра полученной программы prog
,
которые используют единый общий экземпляр разделяемой библиотеки libnew.so
:
$ export LD_LIBRARY_PATH=`pwd` $ ./prog 34:41 : initial buffer state! > 2-й терминал 35:15 : 2-й терминал -------------------------- 35:15 : 2-й терминал > повторение со второго терминала 35:53 : повторение со второго терминала -------------------------- 35:53 : повторение со второго терминала > ^C $ export LD_LIBRARY_PATH=`pwd` $ ./prog 34:52 : initial buffer state! > 1-й терминал 35:05 : 1-й терминал -------------------------- 35:05 : 1-й терминал > повторение с 1-го терминала 35:34 : повторение с 1-го терминала -------------------------- 35:34 : повторение с 1-го терминала > ^C
Прекрасно видно (по чередующимся временным меткам операции, формат <минуты>:<секунды>), что каждый экземпляр программы работает со своей копией буфера, не затирая данные параллельно работающего экземпляра программы: при первой модификации области данных экземпляру создаётся своя независимая копия данных (COW — copy on write).
Предыдущий раздел: | Оглавление | Следующий раздел: |
Подмена имён | Некоторые сравнения |