[计算机]Linux系统调用与ptrace分析

上传人:油条 文档编号:43245098 上传时间:2018-06-05 格式:PDF 页数:12 大小:205.60KB
返回 下载 相关 举报
[计算机]Linux系统调用与ptrace分析_第1页
第1页 / 共12页
[计算机]Linux系统调用与ptrace分析_第2页
第2页 / 共12页
[计算机]Linux系统调用与ptrace分析_第3页
第3页 / 共12页
[计算机]Linux系统调用与ptrace分析_第4页
第4页 / 共12页
[计算机]Linux系统调用与ptrace分析_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《[计算机]Linux系统调用与ptrace分析》由会员分享,可在线阅读,更多相关《[计算机]Linux系统调用与ptrace分析(12页珍藏版)》请在金锄头文库上搜索。

1、Linux 系统调用与 ptrace 分析 Linux 系统调用与 ptrace 分析 概述概述 1Linux的系统结构的系统结构 在 Linux 系统结构中,最核心的是计算机硬件,它提供对 Linux 软件的支持,靠近硬件的 内层是 Linux 内核程序 (即操作系统) 。 内核直接和硬件打交道是程序和硬件之间的接口或界面。 它对一切外层程序提供公共服务,把外部程序同硬件隔离开。内核程序大致可分为文件系统管 理,进程管理,内存管理等几部分。进程管理又分为低级进程管理和高级进程管理。低级进程 管理主要包括:进程调度分配,控制占用处理器的程序和基本的进程通信。高级进程管理主要 包括:进程的创建,

2、终止,进程间通信,进程在内存和外存之间的转储,信号机构和进程间跟 踪控制等。内核程序的外层是实用程序,内核提供对实用程序的支持,两层之间的界面是系统 调用。 内核外的实用程序通过系统调用来和内核打交道。 实现的过程是通过一种特殊的指令 (陷 入指令)进入内核,然后转入相应的系统调用处理程序。这也是本文将主要讨论的问题。 280386 体系结构体系结构 80386 的体系结构承认两类事件。 1. 异常(exceptions) 2. 中断(interrupts) 他们两都会引起“上下文转换”同时建立一个过程或任务,中断可以随时随地发生(包括 在执行程序时)所以用来响应硬件信号。而异常则由指令内部错

3、误引起。 每一个异常或中断都有一个唯一的标识符,在 linux 中被称为向量。 指令内部异常和 NMI(不可屏蔽中断)的中断向量的范围从 031。32-255 的任何向量都可以 用做 1. 可屏蔽中断 2. 编程(调试)异常 至于可屏蔽中断则取决于该系统的硬件配置。外部中断控制器在中断响应周期把中断向量 放到总线上。 3 Linux 系统调用流程概述系统调用流程概述 Linux 系统调用的流程非常简单,它由 0x80 号中断进入系统调用入口,通过使用系统 调用表保存系统调用服务函数的入口地址来实现,本文首先分析一般 Linux 系统调用的流 程,然后再分析 Linux 系统调用 sys_ptr

4、ace(). 一. Linux 系统调用的流程分析 一. Linux 系统调用的流程分析 1.1 设定 0x80 号中断 设定 0x80 号中断 系统启动后,先进行初始化,其中一部分重要的工作在 start_kernel()函数(main.c 中定义) 中进行,在该函数中先做必要的初始化工作(setup_arch()与 paging_init(),各种 trap 入 口就在该函数中通过调用 trap_init()(traps.c)被设置,其中与系统调用有关的是: set_system_gate(0x80, “set_system_gate()”是一宏,它在“system.h”中被定义: #de

5、fine set_system_gate(n,addr) _set_gate( errno = -_res; return -1; 该宏的第一个参数是一类类型参数,它指明系统调用返回值的类型,第二个参数指明系统 调用的名称。参数列表中若还有参数,则第 2i 个参数是系统调用函数的第 i 个参数的类型,第 2i+1 个参数是系统调用函数的第 i 个参数 该宏的主体部分是一内联汇编,在内联汇编中只有一条扩展汇编指令,即“int $0x80” ,该 语句两个冒号后的语句设置输入和输出寄存器。 第一个冒号后的语句指明返回参数(即_res)使用 eax 寄存器。 第二个冒号后面指定接受输入的寄存器,“0

6、“ (_NR_#name),”将参数 name 与“_NR_” 串接起来,形成的标志符存入 eax 寄存器,作为区别系统调用类型的唯一参数,例如设置 name 为“ptrace” ,那么,gcc 编译器将把“_NR_”与之串接,被视为标志符“_NR_ptrace” ,由于 在文件“include/asm-i386/unistd.h”中已定义其为 26,那么,传给 eax 的值将为 26。 后面的语句将参数 arg1,arg2 分别传给寄存器 ebx 和 ecx,在“_syscallX”宏中,有如下约 定: arg1 值存入寄存器 ebx; arg2 值存入寄存器 ecx; arg3 值存入寄存

7、器 edx; arg4 值存入寄存器 esi; arg5 值存入寄存器 edi; 在该宏的最后,判断返回值“_res”是否合法,若为负数,表明在系统调用中出错,将其 绝对值作为出错号赋给全局变量“errno” ,并返回-1,否则返回“_res” 。 该宏的唯一一条汇编指令“int $0x80”使程序流程转入“system_call” 。 1.4 转入 system_call 转入 system_call system_call 是在汇编语言文件“entry.S”中定义的一入口,在 Linux 中,所有的系统调用 都是通过中断“int push %gs; push %fs; push %es;

8、push %ds; pushl %eax; pushl %ebp; pushl %edi; pushl %esi; pushl %edx; pushl %ecx; pushl %ebx; movl $(KERNEL_DS),%edx; mov %dx,%ds; mov %dx,%es; movl $(USER_DS),%edx; mov %dx,%fs; 2 语句“cmpl $(NR_syscalls),%eax”比较 NR_syscalls 与 eax 的大小,如果 eax 大于或 等于 NR_syscalls,表明指定的系统调用函数错误, “jae ret_from_sys_call”使系

9、统调用 直接返回。 3 . 流程进入 ret_from_sys_call,该过程内处理一些系统调用返回前应该处理的事情,如检 测 bottom half 缓冲区,判断 CPU 是否需要重新调度等. 先注意全局变量 intr_count,它虽然不是信号量,但也部分的具有了信号量的作用,表 示已有进程进入 bottom_half,它在系统处理 bottom_half 时增 1,则其为非零。 语句“cmpl $0,SYMBOL_NAME(intr_count)”就是进行上述判断,若非零,处理 bottom half 缓冲区。 ( “jne handle_bottom_half” ) 。 下面两条语句

10、判断 CPU 是否需要重新调度: cmpl $0,SYMBOL_NAME(need_resched) jne reschedule 其中,need_resched 是一全程量,它置位,表示 CPU 需要重新调度,程序转向过程 reschedule,进而,转向 schedule()函数,在该函数中,将其重新置零。 注意,handle_bottom_half 和 reschedule 并不是必需的,只不过在系统运行过程中,随 时都有可能出现需要处理 bottom half 缓冲区或重新调度 CPU,放在系统调用返回前, 有利于它们被及时处理。但这也说明,Linux 不是一个硬实时的操作系统,它可能

11、会 产生延误。 4. 如果 eax 小于 NR_syscalls,system_call 过程接下去执行语句: movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax 该语句以 sys_call_table 为基地址,eax 寄存器中的内容(即系统调用的序号)乘 以 4 为偏移量(因为 long 型为 4 字节) ,即得到所需调用的系统调用函数的入口地址, 将其存入寄存器 eax。 testl %eax,%eax 接着判断寄存器 eax 值是否为 0,若是,表明出错,直接返回,je ret_from_sys_call。 #ifdef _SMP_ GET_P

12、ROCESSOR_OFFSET(%edx) movl SYMBOL_NAME(current_set)(,%edx),%ebx #else movl SYMBOL_NAME(current_set),%ebx 以上语句首先判断是否为多处理器结构,若是,得到当前处理器的偏移值,当前的进 程控制块的指针为 current_setsmp_processor_id(),否则,current_set0即为当前进程 控制块的指针,这样,ebx 寄存器指向当前进程。 movl %db6,%edx movl %edx,dbgreg6(%ebx) 以上两条语句用来保存当前调试信息,在进程控制块 task_str

13、uct 结构中,第 8 项是 debugreg8,用来指示硬件调试信息。在 entry.S 中,定义了一系列宏作为偏移量,用 来得到当前进程的信息,它们是: state = 0 counter = 4 priority = 8 signal = 12 blocked = 16 flags = 20 dbgreg6 = 52 dbgreg7 = 56 exec_domain = 60 这样,在当前进程的 task_struct 结构中,保存了当前的调试信息。 5.语句“testb $0x20,flags(%ebx)”检测当前进程是否正跟踪系统调用,如果不是的话,直 接调用所选系统调用函数,相关语

14、句为: call *%eax 如判断当前进程正处于跟踪系统调用状态(current-flags current-exit_code = SIGTRAP; current-state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); if (current-exit_code) send_sig(current-exit_code, current, 1); current-exit_code = 0; 然后从压入寄存器的堆栈中重新找到原来的 eax 值,再重新设置系统调用函数的偏移量,调用 实现相应系统调用的函数,语句为:

15、 call SYMBOL_NAME(syscall_trace) movl ORIG_EAX(%esp),%eax call *SYMBOL_NAME(sys_call_table)(,%eax,4) 做完以上工作后,将返回值保存在 eax 寄存器中。 movl %eax,EAX(%esp) 最后进入 ret_from_sys_call,作一些处理工作。 二. 系统调用实例分析:二. 系统调用实例分析:ptraceptrace 系统调用 系统调用 2.1 跟踪及跟踪及 ptrace()简述()简述 Linux 提供的跟踪功能, 即父进程对子进程的跟踪, 使得父进程可以对自己的子进程进行监 督与控制。具体包括读写子进程用户空间的程序,数据,或 user 结构中的变量,向它们发送软 中断, 以及命令它们自我终止等。 系统提供了两种系统调用 waitpid()和 ptrace(),一实现跟踪功能。 这种父子进程间的关联可由子进程发 ptrace(0)请求,也可由父进程发 attach 请求来实现. 本文第二部分先利用第一部分的知识阐述 ptrace 系统调用的设置,然后再简单解释 ptrace 系统调用的流程。 2.2 预备知识预备知识 1 标识”错误“的宏,定义在 linuxincludeasm_i386errno.h ptrace()中涉

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号