library linking on LINUX

file list: original files were from chapter 20 of Linux系统分析与高级编程技术

 1. hello2.c --test bench for static linking and linking with shared lib

#include  " Semaphore.h "
#include 
< stdio.h >

void  print_message_function(  void   * ptr );
Semaphore child_counter;
Semaphore worlds_turn;

main( )
{
    pthread_t thread1, thread2;
    
char *message1 = "Hello";
    
char *message2 = "World " ;
    semaphore_init( 
&child_counter );
    semaphore_init( 
&worlds_turn );
    semaphore_down( 
&worlds_turn ); /* world goes second */
    semaphore_decrement( 
&child_counter ); /* value now 0 */
    semaphore_decrement( 
&child_counter ); /* value now -1 */
    
/*
     * * child_counter now must be up-ed 2 times for a thread blocked on it
     * * to be released
     * *
    
*/

    pthread_create( 
&thread1, NULL,(void *&print_message_function, (void *) message1);
    semaphore_down( 
&worlds_turn );
    pthread_create( 
&thread2, NULL,(void *&print_message_function, (void *) message2);
    semaphore_down( 
&child_counter );
    
/* not really necessary to destroy since we are exiting anyway */
    semaphore_destroy ( 
&child_counter );
    semaphore_destroy ( 
&worlds_turn );
    exit( 
0 ) ;
}


void  print_message_function(  void   * ptr )
{
    
char *message;
    message 
= (char *) ptr;
    printf(
"%s ", message);
    fflush(stdout);
    semaphore_up( 
&worlds_turn );
    semaphore_up( 
&child_counter );
    pthread_exit( 
0 ) ;
}

 2. hello2_dl.c -- test bench for dynamic linking

#include  < stdio.h >
#include 
< stdlib.h >
#include 
< dlfcn.h >
#include 
" Semaphore.h "

void  print_message_function(  void   * ptr );
Semaphore child_counter;
Semaphore worlds_turn;

void  ( * initfcn)(Semaphore *  s);
void  ( * destroyfcn)(Semaphore *  s);
int  ( * downfcn)(Semaphore *  s);
int  ( * upfcn)(Semaphore *  s);
int  ( * decfcn)(Semaphore *  s);

int  main( )
{
    pthread_t thread1, thread2;
    
char *message1 = "Hello";
    
char *message2 = "World ";

    
void *handle;
    
const char *errmsg;

    handle 
= dlopen("libSemaphore.so", RTLD_NOW);
    
if(handle == NULL) {
        fprintf(stderr, 
"Failed to load libSempahore.so: %s ", dlerror());
        exit(EXIT_FAILURE);
    }

    dlerror();

    initfcn 
= dlsym(handle, "semaphore_init");
    
if((errmsg = dlerror()) != NULL) {
        fprintf(stderr, 
"Didn't find semaphore_init(): %s ", errmsg);
        exit(EXIT_FAILURE);
    }


    downfcn 
= dlsym(handle, "semaphore_down");
    
if((errmsg = dlerror()) != NULL) {
        fprintf(stderr, 
"Didn't find semaphore_down(): %s ", errmsg);
        exit(EXIT_FAILURE);
    }


   upfcn 
= dlsym(handle, "semaphore_up");
    
if((errmsg = dlerror()) != NULL) {
        fprintf(stderr, 
"Didn't find semaphore_up(): %s ", errmsg);
        exit(EXIT_FAILURE);
    }


    decfcn 
= dlsym(handle, "semaphore_decrement");
    
if((errmsg = dlerror()) != NULL) {
        fprintf(stderr, 
"Didn't find semaphore_decrement(): %s ", errmsg);
        exit(EXIT_FAILURE);
    }



    destroyfcn 
= dlsym(handle, "semaphore_destroy");
    
if((errmsg = dlerror()) != NULL) {
        fprintf(stderr, 
"Didn't find semaphore_destroy(): %s ", errmsg);
        exit(EXIT_FAILURE);
    }


    initfcn( 
&child_counter );
    initfcn( 
&worlds_turn );
    downfcn( 
&worlds_turn ); /* world goes second */
    decfcn( 
&child_counter ); /* value now 0 */
    decfcn( 
&child_counter ); /* value now -1 */
    
/*
     * * child_counter now must be up-ed 2 times for a thread blocked on it
     * * to be released
     * *
    
*/

    pthread_create( 
&thread1, NULL,(void *&print_message_function, (void *) message1);
    downfcn( 
&worlds_turn );
    pthread_create( 
&thread2, NULL,(void *&print_message_function, (void *) message2);
    downfcn( 
&child_counter );
    
/* not really necessary to destroy since we are exiting anyway */
    destroyfcn ( 
&child_counter );
    destroyfcn ( 
&worlds_turn );
    dlclose(handle);
    exit( 
0 ) ;
}


void  print_message_function(  void   * ptr )
{
    
char *message;
    message 
= (char *) ptr;
    printf(
"%s ", message);
    fflush(stdout);
    upfcn( 
&worlds_turn );
    upfcn( 
&child_counter );
    pthread_exit( 
0 ) ;
}

 

3. Semaphore.h Semaphore.c -- lib file

#ifndef SEMAPHORES
#define  SEMAPHORES
#include 
< pthread.h >

typedef 
struct  Semaphore
{
    
int v;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
}
 Semaphore;

int  semaphore_down (Semaphore  *  s);
int  semaphore_decrement (Semaphore  *  s);
int  semaphore_up (Semaphore  *  s);
void  semaphore_destroy (Semaphore  *  s);
void  semaphore_init (Semaphore  *  s);
int  semaphore_value (Semaphore  *  s);
int  tw_pthread_cond_signal (pthread_cond_t  *  c);
int  tw_pthread_cond_wait (pthread_cond_t  *  c, pthread_mutex_t  *  m);
int  tw_pthread_mutex_unlock (pthread_mutex_t  *  m);
int  tw_pthread_mutex_lock (pthread_mutex_t  *  m);
void  do_error ( char   * msg);

# endif

 

#include  " Semaphore.h "
/*
* function must be called prior to semaphore use.
*
*/

void
semaphore_init (Semaphore 
*  s)
{
    s
->= 1;
    
if (pthread_mutex_init (&(s->mutex), NULL) == -1)
        do_error (
"Error setting up semaphore mutex");
    
if (pthread_cond_init (&(s->cond), NULL) == -1)
        do_error (
"Error setting up semaphore condition signal");
}


/*
* function should be called when there is no longer a need for
* the semaphore.
*/

void
semaphore_destroy (Semaphore 
*  s)
{
    
if (pthread_mutex_destroy (&(s->mutex)) == -1)
        do_error (
"Error destroying semaphore mutex");
    
if (pthread_cond_destroy (&(s->cond)) == -1)
        do_error (
"Error destroying semaphore condition signal");
}


/*
* function increments the semaphore and signals any threads that
* * are blocked waiting a change in the semaphore.
*
*/

int
semaphore_up (Semaphore 
*  s)
{
    
int value_after_op;
    tw_pthread_mutex_lock (
&(s->mutex));
    (s
->v)++;
    value_after_op 
= s->v;
    tw_pthread_mutex_unlock (
&(s->mutex));
    tw_pthread_cond_signal (
&(s->cond));
    
return (value_after_op);
}


/*
* function decrements the semaphore and blocks if the semaphore is
* * <= 0 until another thread signals a change.
*
*/

int
semaphore_down (Semaphore 
*  s)
{
    
int value_after_op;
    tw_pthread_mutex_lock (
&(s->mutex));
    
while (s-><= 0)
    
{
        tw_pthread_cond_wait (
&(s->cond), &(s->mutex));
    }

    (s
->v)--;
    value_after_op 
= s->v;
    tw_pthread_mutex_unlock (
&(s->mutex));
    
return (value_after_op);
}


/*
* function does NOT block but simply decrements the semaphore.
 * should not be used instead of down -- only for programs where
 * multiple threads must up on a semaphore before another thread
 * can go down, i.e., allows programmer to set the semaphore to
 * a negative value prior to using it for synchronization.
 *
*/

int
semaphore_decrement (Semaphore 
*  s)
{
    
int value_after_op;
    tw_pthread_mutex_lock (
&(s->mutex));
    s
->v--;
    value_after_op 
= s->v;
    tw_pthread_mutex_unlock (
&(s->mutex));
    
return (value_after_op);
}


/*
* function returns the value of the semaphore at the time the
* critical section is accessed. obviously the value is not guarenteed
* after the function unlocks the critical section. provided only
* for casual debugging, a better approach is for the programmar to
* protect one semaphore with another and then check its value.
* an alternative is to simply record the value returned by semaphore_up
* or semaphore_down.
*
*/

int
semaphore_value (Semaphore 
*  s)
{
    
/* not for sync */
    
int value_after_op;
    tw_pthread_mutex_lock (
&(s->mutex));
    value_after_op 
= s->v;
    tw_pthread_mutex_unlock (
&(s->mutex));
    
return (value_after_op);
}


/* -------------------------------------------------------------------- */
/* The following functions replace standard library functions in that */
/* they exit on any error returned from the system calls. Saves us */
/* from having to check each and every call above. */
/* -------------------------------------------------------------------- */
int
tw_pthread_mutex_unlock (pthread_mutex_t 
*  m)
{
    
int return_value;
    
if ((return_value = pthread_mutex_unlock(m)) == -1)
        do_error (
"pthread_mutex_unlock");
    
return (return_value);
}

int
tw_pthread_mutex_lock (pthread_mutex_t 
*  m)
{
    
int return_value;
    
if ((return_value = pthread_mutex_lock(m)) == -1)
        do_error (
"pthread_mutex_lock");
    
return (return_value);
}

int
tw_pthread_cond_wait (pthread_cond_t 
*  c, pthread_mutex_t  *  m)
{
    
int return_value;
    
if ((return_value = pthread_cond_wait(c, m)) == -1)
        do_error (
"pthread_cond_wait");
    
return (return_value);
}

int
tw_pthread_cond_signal (pthread_cond_t 
*  c)
{
    
int return_value;
    
if ((return_value = pthread_cond_signal(c)) == -1)
        do_error (
"pthread_cond_signal");
    
return (return_value);
}


/*
* function just prints an error message and exits
* *
*/

void
do_error (
char   * msg)
{
    perror (msg);
    exit (
1);
}

 4. Makefile:

all: hello2_static1 hello2_static2  Semaphore.o libSemaphore.a libSemaphore.so hello2_shared hello2_dynamic

#static linking program
#hello2_static1 and hello2_static2 are same
hello2_static1: hello2.c libSemaphore.a
        gcc  hello2.c -o hello2_static1 -lSemaphore -L. -lpthread
hello2_static2: hello2.c Semaphore.o
        gcc hello2.c Semaphore.o -o hello2_static2 -lpthread

Semaphore.o: Semaphore.c
        gcc  -Wall -c Semaphore.c -o Semaphore.o

#create archive for object file
libSemaphore.a: Semaphore.o
        ar rcs libSemaphore.a Semaphore.o

#linking with shared lib
#before executing: setenv LD_LIBRARY_PATH $PWD
hello2_shared: hello2.c libSemaphore.so
        gcc  hello2.c -o hello2_shared -lSemaphore -L. -lpthread

libSemaphore.so: Semaphore.c
        gcc -fPIC -Wall -c Semaphore.c -o Semaphore_PIC.o
        gcc  -Wall -shared -Wl
, -soname , libSemaphore.so .1  -o libSemaphore.so .1.0.0  Semaphore_PIC.o -lc
        ln -s libSemaphore.so
.1.0.0  libSemaphore.so .1
        ln -s libSemaphore.so
.1.0.0  libSemaphore.so

#create object with dynamic linking
hello2_dynamic: hello2_dl.c libSemaphore.so
        gcc  -Wall hello2_dl.c -ldl -o hello2_dynamic -lpthread

clean:
        rm -rf hello2_static1 hello2_static2 Semaphore.o Semaphore_PIC.o libSemaphore.a libSemaphore.so libSemaphore.so
.1  libSemaphore.so .1.0.0  hello2_shared hello2_dynamic

 
3 kinds of set searching path for shared libraries:
(1) setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH }:$YOURPATH
(2) add your serching path to /etc/ld.so.conf, then run ldconfig to update /etc/ld.so.cashe under root account
(3) put your shared libs ot /usr/lib, then create soname links to the specific libs, and run ldconfig under root account to update the cache
 
 2 useful commands:
(1) "ldd" shows needed shared libraries for the file:
ldd hello2_static1 :
libpthread.so.0 => /lib/i686/libpthread.so.0 (0x40033000)
libc.so.6 => /lib/i686/libc.so.6 (0x40048000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
ldd hello2_shared :
libSemaphore.so.1 => /rdhome/robin/programming/Linux_System_Analysis_And_Advanced_Programming_Tech/ch20/libSemaphore.so.1 (0x40018000)
libpthread.so.0 => /lib/i686/libpthread.so.0 (0x40036000)
libc.so.6 => /lib/i686/libc.so.6 (0x4004b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
ldd hello2_dynamic:
libdl.so.2 => /lib/libdl.so.2 (0x40033000)
libpthread.so.0 => /lib/i686/libpthread.so.0 (0x40037000)
libc.so.6 => /lib/i686/libc.so.6 (0x4004c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
(2) "nm" shows all symbols in the object
nm libSemaphore.a:
Semaphore.o:
000002dc T do_error
         U exit
00000000 t gcc2_compiled.
         U perror
         U pthread_cond_destroy
         U pthread_cond_init
         U pthread_cond_signal
         U pthread_cond_wait
         U pthread_mutex_destroy
         U pthread_mutex_init
         U pthread_mutex_lock
         U pthread_mutex_unlock
0000017c T semaphore_decrement
00000068 T semaphore_destroy
00000114 T semaphore_down
00000000 T semaphore_init
000000c4 T semaphore_up
000001bc T semaphore_value
000002a4 T tw_pthread_cond_signal
00000268 T tw_pthread_cond_wait
00000230 T tw_pthread_mutex_lock
000001f8 T tw_pthread_mutex_unlock

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值