我想使用个人“pthread_self”功能。我想重写“pthread_self()”,并在最后,调用真正的“pthread_self”。 在C / C ++中有可能吗?
示例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
pthread_t pthread_self(void)
{
// Do something else.....
// ...
// And finally call to de real pthread_self():
return ::pthread_self(); // This doesn't work
}
main()
{
printf("\nThis is my main thread: %lu\n", pthread_self());
}
答案 0 :(得分:0)
代码似乎是C89而没有main
的返回类型。因此,我建议您删除函数::
中pthread_self()
前面的pthread_self(void)
运算符并重新编译。
也可以通过pthread_self()
pthread_self_2(void)
答案 1 :(得分:0)
是否允许使用虚拟变量(从未使用过载)重载pthread_self()
?
pthread_t pthread_self( bool )
{
// Do something else.....
// ...
// And finally call to de real pthread_self():
printf( "%s\n", __PRETTY_FUNCTION__ );
return ::pthread_self(); // This doesn't work
}
int main()
{
printf( "%s\n", __PRETTY_FUNCTION__ );
pthread_self( false );
printf( "%s\n", __PRETTY_FUNCTION__ );
}
产生
$ g++ test.cpp -lpthread
$ ./a.out
int main()
pthread_t pthread_self(bool)
int main()
$
另外两种方法可能是:
编写一个函数my_pthread_self()
,在任何地方使用它,让它调用真实pthread_self()
有一个宏PTHREAD_SELF
调用您的包装器,内部调用真实的pthread_self()
答案 2 :(得分:0)
以下是有点hacky但应该在C中工作。将以下内容放在标题中,您必须在之前包含或代替<pthread.h>
(但从来没有之后 pthread.h):
pthread_t _pthread_self(void);
#define pthread_self _pthread_self
并在相应的.c文件中:
#include <pthread>
#include "wrapper.h"
#undef pthread_self // undo the hack locally
pthread_t _pthread_self(void)
{
// Do something else.....
// ...
// And finally call to the real pthread_self():
return pthread_self();
}
现在,当您在某个其他文件中编写pthread_self
而不是.c文件时,它会扩展到您的包装函数。在上面的.c文件中,由于这个hack没有完成,包装器内的调用将调用库函数。
答案 3 :(得分:0)
This应该给你一些想法。如果您控制可执行文件的链接,则不需要使用LD_PRELOAD。
答案 4 :(得分:0)
感谢大家。 主要基于@Carl Norum和@Arkadyi展示的这两个链接Intercepting Arbitrary Functions on...和Tutorial: Function Interposition in Linux,我向您展示了一个可能的解决方案:
我有两个源文件和一个Makefile:
<强> mipthread_self.C 强>:
#include <stdio.h>
#include <pthread.h>
#if defined (__STDC__) || defined (__cplusplus) || defined (c__plusplus)
#if defined (__cplusplus) || defined (c__plusplus)
extern "C" {
#endif
pthread_t __real_pthread_self();
pthread_t __wrap_pthread_self(void)
{
printf("This is mipthread_self %lu\n", __real_pthread_self());
return __real_pthread_self();
}
#if defined (__cplusplus) || defined (c__plusplus)
}
#endif
#endif
<强> TEST.C 强>:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void* start_function(void* value)
{
printf("Thread start function is running for: %u\n", (unsigned int)pthread_self());
sleep(5);
pthread_exit(value);
}
int main()
{
int res;
pthread_t thread1, thread2;
void* threadReturnValue;
res = pthread_create(&thread1, NULL, start_function, (void*)"thread-one");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}
printf("Thread1 created with id: %u\n", (unsigned int)thread1);
res = pthread_create(&thread2, NULL, start_function, (void*)"thread-two");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}
printf("Thread2 created with id: %u\n", (unsigned int)thread2);
res = pthread_join(thread1, &threadReturnValue);
if (res != 0) {
perror("Joining of thread failed");
exit(EXIT_FAILURE);
}
printf("%s joined.\n", (char*)threadReturnValue);
res = pthread_join(thread2, &threadReturnValue);
if (res != 0) {
perror("Joining of thread failed");
exit(EXIT_FAILURE);
}
printf("%s joined.\n", (char*)threadReturnValue);
return 0;
}
Makefile :
BIN=test
CFLAGS=-g -m32 -fPIC -Wall $(DEFINES)
TIPO=-m32
PWD=`pwd`
DIR_OBJ=$(PWD)
DIR_BIN=$(DIR_OBJ)
INCLUDES=
LD_LIBRARIES=-L$(DIR_OBJ) -lmipthread -Xlinker --wrap -Xlinker pthread_self -lpthread -lstdc++
$(BIN): libmipthread.a
@echo ""
@echo "Se va a generar el binario $@"
@echo ""
gcc $(CFLAGS) test.C -o $(DIR_BIN)/$@ $(LD_LIBRARIES)
libmipthread.a: mipthread_self.o
ar crv $(DIR_OBJ)/$@ $(DIR_OBJ)/$<
mipthread_self.o: mipthread_self.C
gcc $(CFLAGS) -c ${PWD}/$< -o $(DIR_OBJ)/$@ $(INCLUDES)
clean:
rm $(DIR_OBJ)/*.o
rm $(DIR_OBJ)/*.a
rm $(DIR_OBJ)/test