0

我只是在玩弄 LD_PRELOAD 的概念。在我开始在我的代码中使用 pthread 库函数之前,它似乎工作正常。当我这样做时,我会遇到分段错误。LD_PRELOAD 是否对 pthread 库有某种反感?

这里显示的是程序和 LD_PRELOADed .so 代码。

程序代码

// main.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>

#define USE_PTHREADS

#define NUM_THREADS     8

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

int sum;
float total = 1;
extern int __did_libc_start_main;

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   pthread_mutex_lock( &m );
   sum++;
   total *= total + tid * 0.097891313423578;
   printf( "p%d, tid%d, total = %g, start = %d!\n", getpid(), tid, 
      total, 0 );
   pthread_mutex_unlock( &m );
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   char * p;
   char * m;

   fork();

   p = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 
     -1, 0);
   p[0] = 78;
   printf( "p = %p, p[0] = %d, pid = %d!\n", p, p[0], getpid() );
   m = (char*)malloc( 80 );
   printf( "m = %p!\n", m );
#ifdef USE_PTHREADS // If we disable this part of code, LD_PRELOAD works fine
   for(t=0; t<NUM_THREADS; t++)
   {
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }
   for(t=0; t<NUM_THREADS; t++)
    pthread_join(threads[t], NULL);

   printf( "\n\nTotal = %g\n\n", total );

   /* Last thing that main() should do */
   pthread_exit(NULL);
#endif
   printf( "\n\n%d: Done without major problems\n\n", getpid() );
   return 0;
}

LD_PRELOADed .so 代码

// prelib.c
#define _GNU_SOURCE

//#include <sys/syscall.h>
//#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <dlfcn.h>

typedef pid_t (*getpidType)(void);
typedef void* (*mmapType)(void *addr, size_t len, int prot, int flags,
       int fildes, off_t off);

pid_t getpid(void)
{
    static int first_time = 1;
    static getpidType f;

    printf("Hello, getpid!\n");

    if ( first_time )
    {
        f = (getpidType)dlsym(RTLD_NEXT, "getpid");
        first_time = 0;
    }

    return f();
}
void *mmap(void *addr, size_t len, int prot, int flags,
       int fildes, off_t off)
{
    static int first_time = 1;
    static mmapType f;

    printf( "My mmap!\n" );
    if ( first_time )
    {
        f = (mmapType)dlsym(RTLD_NEXT, "mmap" );
        first_time = 0;
    }

    return f( addr, len, prot, flags, fildes, off );
}

定义 USE_PTHREADS 时出现这样的错误。

My mmap!
<< mutex_trylock >>
<< mutex_unlock >>
Hello, getpid!
p = 0x2ab9bc969000, p[0] = 78, pid = 9763!
m = 0x179d4010!
In main: creating thread 0
My mmap!
<< mutex_trylock >>
My mmap!
<< mutex_trylock >>
<< mutex_unlock >>
Hello, getpid!
p = 0x2ab9bc969000, p[0] = 78, pid = 9762!
m = 0x179d4010!
In main: creating thread 0
My mmap!
<< mutex_trylock >>
Segmentation fault
4

2 回答 2

0

我怀疑这是你唯一的问题,但你的“first_time”黑客没有同步,因此不是线程安全的。您应该pthread_once为此目的使用该功能,或者使用互斥锁或信号量滚动您自己的版本。

于 2012-06-05T15:22:03.973 回答
0

我唯一能想象的是:

printf("p%d, tid%d, total = %g, start = %d!\n", getpid(), tid, total, 0);

应该是 tid% ld

也许您在 64 位上运行并且 long 不是 int 大小的。因此,当它打印浮点数时,它会看到废话,并且您正在崩溃 printf。

于 2012-06-05T17:21:58.180 回答