ptrace是linux系统中为了调试专门设立的一种系统调用。要想调试调试一个进程,有两种方式:

PTRACE_TRACEME和PTRACE_ATTACH。这两种方式的主要区别可以概括为:

PTRACE_TRACEME是子进程主动申请被TRACE。而PTRACE_ATTACH是父进程自己要attach到子进程,相当于子进程是被动的trace。

PTRACE_TRACEME程序设置的框架大概为:

if(pid==0)//child

{

ptrace(PTACE_TRACEME,0,NULL,NULL);

exec(...);

}

else//parent

{

wait(&status);

if(WIFSTOPPED(status))

fprintf(stderr,"%s\n",WSTOPSIG(status);//打印出子进程当前的状态。

}看似简单的代码,其实内核做了大量的工作,我们在此进行详细分析。

当程序执行ptrace系统调用,传入PTRACE_TRACEME函数时,内核执行下面的代码段:

static int ptrace_traceme(void)

{

int ret = -EPERM;

write_lock_irq(&tasklist_lock);

/* Are we already being traced? */

if (!current->ptrace) {

ret = security_ptrace_traceme(current->parent);

/*

* Check PF_EXITING to ensure ->real_parent has not passed

* exit_ptrace(). Otherwise we don't report the error but

* pretend ->real_parent untraces us right after return.

*/

if (!ret && !(current->real_parent->flags & PF_EXITING)) {

current->ptrace = PT_PTRACED;

__ptrace_link(current, current->real_parent);

}

}

write_unlock_irq(&tasklist_lock);

return ret;

}从上面的源码我们可以看出:PTRACE_TRACEME并没有使子进程停止,而是将进行一系列判断之后(父进程是否能对子进程进行跟踪的合法性检查),将子进程链接到父进程的ptrace链表中。

真正导致子进程停止的是exec系统调用,该系统调用成功之后,内核会判断该进程是否被ptrace跟踪,如果被跟踪的话,内核将向该进程发送SIGTRAP信号。该信号将导致当前进程停止。具体的代码如下:

static inline void ptrace_event(int event, unsigned long message)

{

if (unlikely(ptrace_event_enabled(current, event))) {

current->ptrace_message = message;

ptrace_notify((event << 8) | SIGTRAP);

} else if (event == PTRACE_EVENT_EXEC) {

/* legacy EXEC report via SIGTRAP */

if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED)

send_sig(SIGTRAP, current, 0);

}

}我们都知道:SIGTRAP信号是专门为debug设计的,当内核踩中断点的时候(断点就是int 3,相应的回调函数就是do_trap),就会发送这个信号:

asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)

{

siginfo_t info;

memset(&info, 0, sizeof(info));

info.si_signo = SIGTRAP;

info.si_code = TRAP_TRACE;

info.si_addr = (void *)address;

force_sig_info(SIGTRAP, &info, current);

regs->pc += 4;

}

从这里我们可以看出,进程被trace之后,对于子进程的许多操作(尤其是父进程感兴趣的操作)都改变了,目的是为了让父进程感知到这些事件,exec就是一个例子。

此时,父进程的wait操作将被唤醒。我们知道wait操作就是父进程用来检测子进程的退出情况,wait操作返回有三种情况:

1、子进程正常退出

int status;

wait(&status);//status保存了子进程当前的状态

WIFEXITED(status)://如果子进程确实正常退出,则为真

WEXITSTATUS(status)://打印出进程的退出码

2、子进程因为收到信号而退出

int status;

wait(&status);

WIFSIGNALED(status)://如果子进程确实正常退出,则为真

WTERMSIG(status)://打印出进程的退出码

3、子进程因为收到信号而暂停

int status;

wait(&status);

WIFSTOPPED(status)://如果子进程确实正常退出,则为真

WSTOPSIG(status)://打印出进程的退出码 显然,PTRACE_TRACEME对应的就是第三种情况。如果想要输出信号对应的描述性字符串,可以这样操作:

sprintf(stderr,"%s\n",WSTOPSIG(status));

linux ptrace 内核源码分析,linux 3.5.4 ptrace源码分析分析(系列一)相关推荐

  1. linux纯内核直接用吗,Linux:为啥内核有的变量没有初始化就敢直接使用?

    一.问题 为啥内核有的变量没有初始化就敢直接使用? 二.分析 看上图,其中的5747行的变量nid的确没有定义,就直接使用了,这么做没有问题吗? 其实大家仔细看一下,5765行是一个宏, 到内核源码去 ...

  2. linux降内核版本_查看linux版本内核 Linux内核版本的变化

    1.major:表示主版本号,有结构性变化时才变更. 2.minor:表示次版本号,新增功能时才发生变化;一般奇数表示测试版,偶数表示生产版. 3.patch:表示对次版本的修订次数或补丁包数. 4. ...

  3. mint linux更新内核,如何在Ubuntu/Linux Mint中安装最新Linux 5.2.5内核

    原标题:如何在Ubuntu/Linux Mint中安装最新Linux 5.2.5内核 Linux 5.2的Ubuntu主线内核包最终可以在32位和64位操作系统中下载和安装. 由于构建失败,Linux ...

  4. linux cifsutils 内核,Veeam Agent for Linux 4.0 安装部署

    官方说明: 硬件要求: CPU:x86-64处理器(i386或更高版本). 内存:1 GB RAM或更大.内存消耗量因备份类型和备份的数据. 磁盘空间:用于产品安装的100 MB可用磁盘空间. 网络: ...

  5. linux编译内核实验,实验六 Linux内核编译实验.doc

    实验六 Linux内核编译 讲师:杨行 [实验目的] 1.掌握Linux内核编译 2.了解Linux内核Makefile 3.了解Linux内核Kbuild系统 [实验原理] 网站可以下载标准内核文件 ...

  6. linux驱动内核哪个文件夹,linux设备驱动归纳总结(一):内核的相关基础概念...

    linux设备驱动归纳总结(一):内核的相关基础概念 1. 内核与 linux 设备驱动的作用与关系 内核:用于管理软硬件资源,并提供运行环境.如分配 4G 虚拟空间等. linux 设备驱动:是连接 ...

  7. linux裁剪内核和移植,嵌入式Linux内核裁剪及移植的研究与实现

    摘要: 嵌入式操作系统是嵌入式系统的软件核心,它管理系统中所有的软件和硬件资源,并且满足嵌入式系统的专用性和可裁剪性.嵌入式Linux以其开源,可裁剪以及模块化设计等特点,吸引了国内外众多研发人员的青 ...

  8. linux中内核4c,一台Linux服务器(4C8G配置)可以负载百万个连接?

    首先我们来看如何标识一个TCP连接?系统是通过一个四元组来识别,(src_ip,src_port,dst_ip,dst_port)即源IP.源端口.目标IP.目标端口.比如我们有一台服务192.168 ...

  9. linux 调整 内核空间占用cpu,[Linux性能优化]3.CPU使用率100%,怎么办?

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? CPU使用率是单位时间内CPU使用情况的统计,以百分比的方式展示. CPU时间是Linux通过事先定义的节拍率(内核中表 ...

  10. linux 替换内核 img,查看更改linux内核initrd.img-Go语言中文社区

    2.6以前的版本采用的是ext2格式的initrd,2.6及以后是cpio包形式,具体来看下吧 2.6及以后版本内核 解包 查看ubuntu的grub.cfg文件 红框是root文件系统,挂载在根目录 ...

最新文章

  1. 【ios开发/Xcode】使用UITableView完成学生信息及成绩的显示
  2. 4一20ma电流有源与无源区别_4-20 mA电流环的工作原理是怎么样的
  3. C/Cpp / Cpp 中 struct 和 class 区别
  4. 带参数的URLconf
  5. 《当程序员的那些狗日日子》(三十六)无名的配角
  6. LeetCode 349. 两个数组的交集(哈希)
  7. 详细讲解Spring中的@Bean注解
  8. 【信息系统项目管理师】第4章-项目整体管理 知识点详细整理
  9. WinForm模拟单击按钮两种方法
  10. python速学_【Python杂货铺】速学python基础
  11. cdh安装hadoop组件后一些常用设置
  12. GIS开发实习地图符号图式制作
  13. Adobe系列软件-快捷键(PS-Photoshop、PR-Premiere Pro、AE-After Effects)
  14. 堆排序算法知识点总结
  15. 龙芯 Linux usb,使用debirf制作龙芯2F的LiveUSB
  16. cdoj1633 去年春恨却来时,落花人独立,微雨燕双飞
  17. T470 Win10下触摸板手势
  18. 45本程序员圣经级别书籍,包邮送到家
  19. 吴松计算机学院,IT|“创青春”创业大赛计算机学院选拔赛成功举行!
  20. Unity热更新机制

热门文章

  1. 完全编译安装boost
  2. mysql datetime 间隔,MySQL datetime默认时间间隔
  3. mysql group by 重复_mysql – 使用GROUP BY删除重复项的查询
  4. 网站添加页面热力图--百度统计
  5. java对两个表进行排序_Excel工作簿中多个worksheet工作表,如何对工作表进行排序?...
  6. java map与set的区别_java 集合(list,set,map)三者之间的关系和区别
  7. 盘点和程序员相关的那些事,让你不再被割韭菜,薅羊毛!
  8. 高内聚,低耦合——8大核心中间件,微服务基础技术栈技术图谱
  9. 在HTML中嵌入PHP代码,有以下几种方法,其中错误的是( )
  10. linux cpu负载巡检,linux服务器巡检报告.doc