链接自己编译的libpthread.so

文章讲述了作者如何从glibc源码编译libpthread库,并尝试将其链接到自己的程序中,以及如何通过修改LD_PRELOAD环境变量来确保使用自编译库的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        最近在看 pthread 的源码,因为这个源码是在 glibc 源码里的,所以可以下载 glibc 源码进行编译,相应的 libpthread 库也会编译出来。我下载的版本是 glibc-2.17,那要使用自己编译出来的 libpthread.so 该如何操作呢?

        首先 libpthread 库的位置要准备好,如把编译好的 libpthread.so 放到了当前目录下:

然后修改编译链接库的位置, 如:-L./ -lpthread,那这样就可以了吗?Makefile 如下:

COMPILE_DIR = compile
BIN_DIR = bin

CC = $(CROSS)gcc
CFLAGS = -Werror -g 

LIB = -L./ -lpthread

SRCS = $(shell ls -t | grep "\.c$$" | head -1)
OBJS = $(patsubst %.c, $(COMPILE_DIR)/%.o, $(SRCS))

DEP = $(patsubst %.o, %.d, $(OBJS))

$(shell if [ ! -d $(COMPILE_DIR) ]; then mkdir $(COMPILE_DIR); fi)
$(shell if [ ! -d $(BIN_DIR) ]; then mkdir $(BIN_DIR); fi)


TARGET=$(BIN_DIR)/a.out

all: $(TARGET)

-include $(DEP)

$(TARGET): $(OBJS)
	$(CC) $(INCLUDE) $(CFLAGS) $^ -o $@ $(LIB)

$(COMPILE_DIR)/%.o: %.c $(COMPILE_DIR)/%.d
	$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ $(LIB)


$(COMPILE_DIR)/%.d: %.c
	$(CC) $(CFLAGS) $(INCLUDE) -MM -E -c $< -o $@
	@sed 's/.*\.o/$(subst /,\/,$(dir $@))&/g' $@ > $@.tmp
	@mv $@.tmp $@

.PHONY: clean
clean:
	rm -rf $(COMPILE_DIR) $(BIN_DIR)
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>

#define handle_error_en(en, msg) \
	   do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

#define handle_error(msg) \
	   do { perror(msg); exit(EXIT_FAILURE); } while (0)

static void *thread_start(void *arg)
{	
	size_t stack_size = 0;
	pthread_attr_t attr;
	printf("in child thread id: %lu\n", *((pthread_t*)arg));
	int ret = pthread_getattr_np(pthread_self(), &attr);
	if(ret != 0)
	{
		handle_error_en(ret, "pthread_attr_init");
	}
	ret = pthread_attr_getstacksize(&attr, &stack_size);
	if (ret != 0)
	{
	   handle_error_en(ret, "pthread_attr_setstacksize");
	}
	printf("current thread stack_size = %lu\n", stack_size);

	sleep(200);
	return 0;
}

void (*cancel_hook) (void *);
int main(int argc, char *argv[])
{
	int s, tnum, opt, num_threads;
	pthread_t thread_id;
	pthread_attr_t attr;
	int stack_size = 0x80000;
	void *res;
	printf("pid of a.out %lu\n", getpid());
	printf("sizeof(pthread_mutex_t) = %lu\n", sizeof(pthread_mutex_t));
	
	printf("pointer of function = %lu\n", sizeof(cancel_hook));
	/* Initialize thread creation attributes */
	s = pthread_attr_init(&attr);
	if (s != 0)
	{
	   handle_error_en(s, "pthread_attr_init");
	} 

	if (stack_size > 0) 
	{
	   s = pthread_attr_setstacksize(&attr, stack_size);
	   if (s != 0)
	   {
		   handle_error_en(s, "pthread_attr_setstacksize");
	   }
	}


	printf("set stack size %lu\n", stack_size);
	s = pthread_create(&thread_id, &attr, &thread_start, &thread_id);

	if (s != 0)
	{
	   handle_error_en(s, "pthread_create");
	}
	printf("the child threadId %lu\n", thread_id);

	/* Destroy the thread attributes object, since it is no
	  longer needed */
	s = pthread_attr_destroy(&attr);
	if (s != 0)
	{
	   handle_error_en(s, "pthread_attr_destroy");
	}

	s = pthread_join(thread_id, &res);
	if (s != 0)
	{
	   handle_error_en(s, "pthread_join");
	}

	exit(EXIT_SUCCESS);
}

编译链接是没有问题的,我们看一下执行结果:

执行结果并不是我想要的,没有链接到我编译的 libpthread.so,因为我在线程创建函数里添加了打印,这里没有看到我想要的结果。用 ldd 查看一下链接是线程库:

程序链接的还是系统的线程库,而不是我编译出来的线程库。这样看来还没有执行前,链接的线程就是系统的线程库。那这个是否可以改呢?修改 LD_PRELOAD 环境变量,使用 export LD_PRELOAD=./libpthread.so,再用 ldd 看链接的就是编译出来的 libpthread.so了。

执行结果就是想要的结果,然后就可以编译 debug 版本的线程库,供学习使用了。

 总结:

1,指定链接路径 -L 及库 -lpthread

2,设置 LD_PRELOAD

尝试过修改库名称,如 libmypthread,及添加 -L./ -lmypthread,然后修改 LD_PRELOAD=./libmypthread.so,但不管执行什么命令都会出现这个错误,不知为何。

链接这个自编译的 libpthrea.so 库只是学习使用,而且 export LD_PRELOAD 也只是当前shell窗口可用,只是一个临时设置, 想取消只需要 unset LD_PRELOAD 即可, 这样之后线程库又会链接到系统默认的库上了。 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值