linux之使用ptrace 跟踪多线程程序

Posted yunshouhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux之使用ptrace 跟踪多线程程序相关的知识,希望对你有一定的参考价值。

1.ptrace 原型说明

 #include <sys/ptrace.h>
 long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);

 在使用PTRACE_TRACEME参数时,跟踪多线程程序需要使用PTRACE_SETOPTIONS来设置ptrace相关属性。

 PTRACE_SETOPTIONS 是将父进程内由data指向的值设定为ptrace 选项,data作为掩码来解释,由下面的标志来指定:

    (1) PTRACE_O_EXITKILL:当跟踪进程退出时,向所有被跟踪进程发送SIGKILL信号将其退出,这个参数可以防止被跟踪进程脱离跟踪进程的控制。

    (2) PTRACE_O_TRACECLONE:被跟踪进程在下一次调用clone()时将其停止,并自动跟踪新产生的进程,新产生的进程刚开始收到SIGSTOP信号。其新产生的进程的pid可以  

        通过PTRACE_GETEVENTMSG得到。

    (3) PTRACE_O_TRACEEXEC:被跟踪进程在下一次调用exec()函数时使其停止。

    (4) PTRACE_O_TRACEEXIT:被跟踪进程在退出是停止其执行,被跟踪进程的退出状态可通过PTRACE_GETEVENTMSG获得。

    (5) PTRACE_O_TRACEFORK:被跟踪进程在下次调用fork()时停止执行,并自动跟踪新产生的进程,新产生的进程刚开始收到SIGSTOP信号。其新产生的进程的pid可以  

        通过PTRACE_GETEVENTMSG得到。

    (6) PTRACE_O_TRACEVFORK:被跟踪进程在下次调用vfork()时停止执行,并自动跟踪新产生的进程,新产生的进程刚开始收到SIGSTOP信号。其新产生的进程的pid可以  

          通过PTRACE_GETEVENTMSG得到。

  PTRACE_GETEVENTMSG:获取刚刚发生的ptrace事件消息,并存放在跟踪进程由data指向的位置,addr参数被忽略。对于

  PTRACE_EVENT_FORK,PTRACE_EVENT_VFORK,PTRACE_EVENT_VFORKDOWN和PTRACE_EVENT_CLONE,data是新进程的pid.

#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>

void *thread_function(void *arg);
char message[] = "hello";
int main()

	int res;
	pthread_t a_thread;
	void *thread_result;
	res = pthread_create(&a_thread, NULL, thread_function, (void*) message);
	if (res != 0)
	
		printf("Thread creation failed");
		exit(EXIT_FAILURE);
	
	printf("Wait for thread to finish...\\n");
	//等待上面线程结束
	res = pthread_join(a_thread, &thread_result);
	if (res != 0)
	
		perror("Thread join failed");
		exit(EXIT_FAILURE);
	
	printf("Thread joined, it returned %s\\n", (char *) thread_result);
	exit(EXIT_SUCCESS);
	//return 0;


void *thread_function(void *arg)

	printf("thread_function is running ,Argument was %s\\n", (char*)arg);
	pthread_exit("Thank you for the CPU time");

#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>


//http://www.xuebuyuan.com/1572720.html
int main()

	pid_t child_pid;
	int status = 0;

	if ((child_pid = fork()) == 0) //子进程返回
	
		ptrace(PTRACE_TRACEME, 0, NULL, NULL);
		execl("/bin/ping", "ping www.baidu.com", 0);//这个路径需要更改
		printf("child process start failed...\\n");
	
	else
	
		wait(NULL); //接收SIGTRAP信号
		long ptraceOption = PTRACE_O_TRACECLONE;
		ptrace(PTRACE_SETOPTIONS, child_pid, NULL, ptraceOption); //设置ptrace属性PTRACE_SETOPTIONS

		ptrace(PTRACE_CONT, child_pid, NULL, NULL);

		while (1)
		
			printf("parent process wait child pid \\n");
			pid_t child_waited = waitpid(-1, &status, __WALL);//等待接收信号
         

			if (WIFSTOPPED(status))
			
				printf("child %ld recvied signal %d\\n", (long)child_waited, WSTOPSIG(status));
			

			if (WIFSIGNALED(status))
			
				printf("child %ld recvied signal %d\\n", (long)child_waited, WTERMSIG(status));
			

			if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)
			 //新线程被创建完成后,收到的信号,或者遇到断点时

				ptrace(PTRACE_CONT, child_waited, 1, NULL);
				continue;
			

			if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP)
			
			    //当一个线程创建另一个线程返回时,收到的信号
				pid_t new_pid;
				if (((status >> 16) & 0xffff) == PTRACE_EVENT_CLONE)
				
					if (ptrace(PTRACE_GETEVENTMSG, child_waited, 0, &new_pid)
					        != -1)
					
						printf("thread %d created\\n", new_pid);

					

				
			

			if (child_waited == -1)
				break;

			if (WIFEXITED(status))
			 //线程结束时,收到的信号
				printf("thread %d exited with status %d\\t\\n",
					child_waited,
					WEXITSTATUS(status));
			

			ptrace(PTRACE_CONT, child_waited, 1, NULL);
		

	

	return 0;






















以上是关于linux之使用ptrace 跟踪多线程程序的主要内容,如果未能解决你的问题,请参考以下文章

linux禁止gdb调试

通过内核编译法向Linux内核添加系统调用

在docker中使用gdb调试程序

Linux-Ubuntu open-mpi运行错误

多线程之线程同步(互斥锁信号量条件变量和读写锁​)

多线程之线程同步(互斥锁信号量条件变量和读写锁​)