Библиотека сайта 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).
| Предыдущий раздел: | Оглавление | Следующий раздел: |
| Подмена имён | Некоторые сравнения |
