1、ptrace的说明

ptrace原型:

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

ptrace跟踪多进程时,需要通过ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions),即PTRACE_SETOPTIONS设置ptrace的相关属性,也就是将data指向的值设定为ptrace的选项,可选的有:

(1)PTRACE_O_TRACEFORK:被跟踪进程在下次调用fork()时停止执行,并自动跟踪新产生的进程,新产生的进程刚开始运行就收到SIGSTOP信号。其新产生的进程的pid可以通过PTRACE_GETEVENTMSG得到(即:ptrace(PTRACE_GETEVENTMSG, child_waited, 0, &new_pid)。

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

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

(4)PTRACE_O_TRACEEXEC:被跟踪进程在下一次调用exec()函数时使其停止,PTRACE_GETEVENTMSG可用于获取发生execve的old_pid(即:ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid))。

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

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

2、strace与linux内核的交互

strace-4.8,linux-3.10.1

以下就针对上面加粗部分,分析strace对新进程的处理以及linux内核对这部分功能的支持

fork、vfork、clone系统调用最后都会调用do_fork,只是传递的参数不同。

SYSCALL_DEFINE0(fork)
{
#ifdef CONFIG_MMU
return do_fork(SIGCHLD, , , NULL, NULL);
#else
/* can not support in nommu mode */
return(-EINVAL);
#endif
}
SYSCALL_DEFINE0(vfork)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, ,
, NULL, NULL);
}
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
int __user *, parent_tidptr,
int __user *, child_tidptr,
int, tls_val)
{
return do_fork(clone_flags, newsp, , parent_tidptr, child_tidptr);
}

在do_fork中,此处截取和ptrace相关的部分:

long do_fork(unsigned long clone_flags,
unsigned long stack_start,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
{
... /*
* Determine whether and which event to report to ptracer. When
* called from kernel_thread or CLONE_UNTRACED is explicitly
* requested, no event is reported; otherwise, report if the event
* for the type of forking is enabled.
*/
if (!(clone_flags & CLONE_UNTRACED)) {
if (clone_flags & CLONE_VFORK)//根据cloneflags判断陷入strace的event
trace = PTRACE_EVENT_VFORK;
else if ((clone_flags & CSIGNAL) != SIGCHLD)
trace = PTRACE_EVENT_CLONE;
else
trace = PTRACE_EVENT_FORK; if (likely(!ptrace_event_enabled(current, trace)))//if(value),判断task->ptrace没设置该ptrace event则将trace置0
trace = ;
} p = copy_process(clone_flags, stack_start, stack_size,
child_tidptr, NULL, trace);//trace是ptrace中相应的setoptions(fork等陷入
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
*/
if (!IS_ERR(p)) {
struct completion vfork; trace_sched_process_fork(current, p); nr = task_pid_vnr(p); ... wake_up_new_task(p);//将进程唤醒并添加到就绪队列中等待调度 /* forking complete and child started to run, tell ptracer*/
if (unlikely(trace))//不进入执行可能性大,但是如果strace设置了该trace事件陷入,则进入执行
ptrace_event(trace, nr);//此处nr是子进程pid,为了让strace可以通过PTRACE_GETEVENTMSG获得该子进程pid ...
} else {
nr = PTR_ERR(p);
}
return nr;
}

在copy_process中,有

if (likely(p->pid)) {
ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);//设置子进程被ptrace
...
}

最重要的部分,对应“并自动跟踪新产生的进程,新产生的进程刚开始运行就收到SIGSTOP信号”:

/**
* ptrace_init_task - initialize ptrace state for a new child
* @child: new child task
* @ptrace: true if child should be ptrace'd by parent's tracer
*
* This is called immediately after adding @child to its parent's children
* list. @ptrace is false in the normal case, and true to ptrace @child.
*
* Called with current's siglock and write_lock_irq(&tasklist_lock) held.
*/
static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
{//设置子进程ptrace,如果子进程应该被追踪父进程的strace追踪的话,此ptrace值为1
INIT_LIST_HEAD(&child->ptrace_entry);
INIT_LIST_HEAD(&child->ptraced);
#ifdef CONFIG_HAVE_HW_BREAKPOINT
atomic_set(&child->ptrace_bp_refcnt, );
#endif
child->jobctl = ;
child->ptrace = ;
child->parent = child->real_parent; if (unlikely(ptrace) && current->ptrace) {
//父进程被trace的标志给子进程,因为有了相应的ptrace标志(PT_TRACED),导致内核在投递信号时,先检查task_struct的ptrace字段的该标志,若有,则设置进程状态TASK_STOPPED,以中断执行子进程,而后notify_parent和CHLD信号用于通知tracer,tracer可设置PTRACE_SYSCALL使该进程之后发生和完成syscall也会陷入到strace,即没通过attach做这个跟踪,而是内核直接设置了标志,更加直接,不用用户层的系统调用ptrace
child->ptrace = current->ptrace;
__ptrace_link(child, current->parent); if (child->ptrace & PT_SEIZED)
task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
else
sigaddset(&child->pending.signal, SIGSTOP);//给子进程child设置SIGSTOP信号 set_tsk_thread_flag(child, TIF_SIGPENDING);//给子进程child设置TIF_SIGPENDING标志,说明该进程有延迟的信号(SIGSTOP)要等待处理。该子进程被调度时,在进程返回用户空间前,会调用do_notify_resume()处理该进程的信号
}
}

此处就设置了子进程有未处理的SIGSTOP信号,导致该子进程被调度时,收到SIGSTOP信号,又因为该子进程被strace跟踪,所以该子进程因SIGSTOP陷入到strace中,strace就在第一时刻捕获到该子进程,strace会发现已被追踪链表中没有该子进程pid,则为该子进程新建file和tcb,并设置相应option。

进程的do_fork中在copy_process后会wake_up_new_process把子进程放到运行队列中,然后执行到ptrace_event,会导致父进程SIGTRAP陷入到strace中。此处对应“被跟踪进程在下次调用fork()时停止执行,新产生的进程的pid可以通过PTRACE_GETEVENTMSG得到”:

/**
* ptrace_event - possibly stop for a ptrace event notification
* @event: %PTRACE_EVENT_* value to report
* @message: value for %PTRACE_GETEVENTMSG to return
*
* Check whether @event is enabled and, if so, report @event and @message
* to the ptrace parent.
*
* Called without locks.
*/
static inline void ptrace_event(int event, unsigned long message)
{
if (unlikely(ptrace_event_enabled(current, event))) {
current->ptrace_message = message;//让PTRACE_GETEVENTMSG可获得fork等的子进程pid(strace没用这个,strace是通过wait到新pid就是新进程,但获取发生execve的old_pid用
ptrace_notify((event << ) | SIGTRAP);//如果ptrace设置了该event事件选项,则SIGTRAP陷入strace程序(可以通过geteventmsg得到old_pid
} else if (event == PTRACE_EVENT_EXEC) {//发生execve则SIGTRAP陷入strace
/* legacy EXEC report via SIGTRAP */
if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED)
send_sig(SIGTRAP, current, );
}
}

补充:

用户态:ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid)

走到内核是:SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,unsigned long, data)->arch_ptrace->ptrace_request->ret = put_user(child->ptrace_message, datalp);也就是这样把message传给用户态来获取。

strace跟踪多进程与内核的交互的更多相关文章

  1. ftrace:跟踪你的内核函数! | Linux 中国

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79161135 ftrace 是一个 L ...

  2. [strace]跟踪进程的系统调用

    转自:https://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html 简介 strace常用来跟踪进程执行时的系统调用和所接收的信号 ...

  3. register_sysctl_table实现内核数据交互

    作者:Younger Liu, 本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可. Sysctl是一种用户应用来设置和获得运行时内核的配置参数的一种有效方式,通 ...

  4. Strace跟踪解决expect乱码问题

    --Strace跟踪解决expect乱码问题 ----------------------------------2014/07/27 情景:需要在本机抓去另外一台远程数据库中的数据. 执行语句:./ ...

  5. 跟踪分析Linux内核的启动过程--实验报告 分析 及知识重点

    跟踪分析Linux内核的启动过程 攥写人:杨光  学号:20135233 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.stud ...

  6. 20135202闫佳歆--week3 跟踪分析Linux内核的启动过程--实验及总结

    实验三:跟踪分析Linux内核的启动过程 一.调试步骤如下: 使用gdb跟踪调试内核 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd r ...

  7. 跟踪分析Linux内核的启动过程小解

    跟踪分析Linux内核的启动过程 “20135224陈实  + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029 ...

  8. 深入理解Linux网络技术内幕——用户空间与内核空间交互

    概述:     内核空间与用户空间经常需要进行交互.举个例子:当用户空间使用一些配置命令如ifconfig或route时,内核处理程序就要响应这些处理请求.     用户空间与内核有多种交互方式,最常 ...

  9. 实验三:跟踪分析Linux内核的启动过程

    实验三:跟踪分析Linux内核的启动过程 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处   <Linux内核分析>MOOC课程http://mooc.study.16 ...

随机推荐

  1. centos安装Django之三:安装python

    这是centos安装Django系列第三篇,安装python.centos系统已经自带了python2.6,但是它被系统很多程序所依赖,不建议删除.我们可以使用以下命令来查看我们使用的Python版本 ...

  2. 20170731 培训Bootstrap

    Bootstrap使用 涉及培训内容框架:--1 html html为标记语言,可以理解为容器,就是用来承载你想要展示到网页的内容的容器.版本也有很多,不同版本表示不同的标记的新增或者取代. Boot ...

  3. Python3学习之路~6.3 类变量 VS 实例变量

    类变量 VS 实例变量 #Author:Zheng Na # 实例里面可以查询.增加.删除.修改实例变量 class Role: # 类名 # 类变量 name = '我是类name' n=1 n_l ...

  4. abap method中的异常处理

    1: 抛出异常 2: 处理异常

  5. Entity Framework学习初级篇3--LINQ TO Entities

    LINQ 技术(即LINQ to Entities)使开发人员能够通过使用LINQ 表达式和LINQ 标准查询运算符,直接从开发环境中针对实体框架对象上下文创建灵活的强类型查询.LINQ to Ent ...

  6. android studio 编译sdk版降低报错解决方法

    解决办法如下: 步骤1:在gradle中修改 compile sdk 版本,比如 8. 步骤2:在gradle中删除v7包的依赖 步骤3:在manifest中修改theme,supportsRtl.t ...

  7. antlr安装

    安装java环境,环境变量设置如下: ANTLR 简介 ANTLR—Another Tool for Language Recognition,Antlr 本身是使用 Java 开发的,它为包括Jav ...

  8. HDU 4686 Arc of Dream(矩阵)

    Arc of Dream [题目链接]Arc of Dream [题目类型]矩阵 &题解: 这题你做的复杂与否很大取决于你建的矩阵是什么样的,膜一发kuangbin大神的矩阵: 还有几个坑点: ...

  9. POJ 2752 Seek the Name,Seek the Fame(KMP,前缀与后缀相等)

    Seek the Name,Seek the Fame 过了个年,缓了这么多天终于开始刷题了,好颓废~(-.-)~ 我发现在家真的很难去学习,因为你还要陪父母,干活,做家务等等 但是还是不能浪费时间啊 ...

  10. c#中的模态对话框和非模态对话框

    模态对话框弹出窗口阻止调用窗口的所有消息响应.只有在弹出窗口结束后调用窗口才能继续.在模态窗口“关闭”后,可以读取模态窗口中信息,包括窗口的返回状态,窗口子控件的值. 非模态对话框可以在弹出窗口和调用 ...