下面的代码演示了使用
LD_PRELOAD
时,可以在同一个进程中多次加载库(多次调用构造函数,多次初始化静态数据)。
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
extern bool initialized = false;
void __attribute__ ((constructor)) setup() {
printf("constructor %d %d %d\n", getpid(), gettid(), initialized);
initialized = true;
}
可以使用以下命令运行实验:
$ gcc -Wall -shared -fPIC -o libtest.so lib.c
$ env LD_PRELOAD=$PWD/libtest.so sh -c "$cmd"
constructor 98928 98928 0
constructor 98928 98928 0
... rest of output of $cmd
注意PID是一样的;这不是分叉造成的问题。请注意, initialized
变量为 0,大概是因为每次加载库时,加载器都会将静态部分放入新的内存中。我知道将
sh -c "$cmd"
替换为
$cmd
会导致库在这种特殊情况下仅加载一次,但通常不会(
$cmd
本身可能是对
sh -c
的调用)。如何在
LD_PRELOAD
ed 库中只运行一次代码?人们想要使用
LD_PRELOAD
来完成的许多任务都需要进程全局数据。
sh
时,库将被加载,并且构造函数将运行。然后,由于
-c "$cmd"
,shell 调用
exec
例程,用新程序完全替换该进程。几乎先前程序的所有内容都被擦除,包括加载的库。然后新程序启动,因此库再次加载,构造函数再次运行。它不会在同一个程序中运行构造函数两次。
我知道将
sh -c "$cmd"
替换为$cmd
会导致库在这种特殊情况下仅加载一次,…如何在
ed 库中只运行一次代码?LD_PRELOAD
在书写时,将
sh -c "$cmd"
替换为 $cmd
。
本身可以是对$cmd
的调用sh -c
不,不是。
$cmd
本身告诉您当前的 shell 执行 $cmd
。 sh -c $cmd
告诉您当前的 shell 创建一个新 shell 并让它执行 $cmd
。