当前位置: 首页 > news >正文

Linux的系统调用是怎么样运行的

一、辅助函数

1. entry文件概述

  • 作用:处理系统调用、中断、异常(如缺页、除零错误等),以及任务切换(如信号处理、调度)。
  • 关键特性
    • 保存/恢复寄存器状态。
    • 系统调用入口(system_callsysenter_entry)。
    • 中断处理(common_interrupt)。
    • 异常处理(如 divide_errorpage_fault)。
    • 返回用户空间的逻辑(ret_from_exceptionresume_userspace)。

2. 核心数据结构

栈布局(Stack Layout)

ret_from_system_call 时,栈的结构如下(偏移量从 %esp 开始):

0(%esp)  - %ebx       | 通用寄存器保存顺序(SAVE_ALL 宏)
4(%esp)  - %ecx       |
8(%esp)  - %edx       |
C(%esp)  - %esi       |
10(%esp) - %edi       |
14(%esp) - %ebp       |
18(%esp) - %eax       | 返回值或系统调用号
1C(%esp) - %ds        | 段寄存器
20(%esp) - %es        |
24(%esp) - orig_eax   | 原始系统调用号(可能被修改)
28(%esp) - %eip       | 用户态返回地址
2C(%esp) - %cs        | 代码段寄存器
30(%esp) - %eflags    | CPU 标志寄存器
34(%esp) - %oldesp    | 用户态栈指针
38(%esp) - %oldss     | 用户态栈段寄存器

3. 关键宏定义

3.1.寄存器保存与恢复

3.1.1.SAVE_ALL
#define SAVE_ALL \cld; \pushl %es; \pushl %ds; \pushl %eax; \pushl %ebp; \pushl %edi; \pushl %esi; \pushl %edx; \pushl %ecx; \pushl %ebx; \movl $(__USER_DS), %edx; \movl %edx, %ds; \movl %edx, %es;

这段代码是 Linux 内核(x86 架构)中用于保存进程上下文的宏定义,通常出现在系统调用、中断或异常处理的入口处。它的核心作用是将寄存器状态保存到内核栈,并设置正确的段寄存器,以确保内核代码能安全访问用户空间数据。

cld

  • 作用:清除方向标志位(Direction Flag,DF)。
    • 内核要求:DF 必须为 0(默认递增),避免字符串操作反向执行导致错误。
    • 用户态可能设置 DF=1:因此在进入内核时需显式清除。

保存段寄存器 esds

pushl %es;
pushl %ds;
  • 作用:将 esds 寄存器的值压入内核栈。
    • dses 是数据段寄存器。
    • 内核需要保存用户态的段寄存器值,以便后续恢复(如返回用户态时)。

保存通用寄存器

pushl %eax;
pushl %ebp;
pushl %edi;
pushl %esi;
pushl %edx;
pushl %ecx;
pushl %ebx;
  • 作用:按顺序保存 eaxebpediesiedxecxebx 到内核栈。

设置段寄存器

movl $(__USER_DS), %edx;  // 加载用户数据段选择子到 edx
movl %edx, %ds;           // 设置 ds = 用户数据段
movl %edx, %es;           // 设置 es = 用户数据段
  • 作用:将 dses 设置为用户数据段选择子__USER_DS)。
  • 此处设置 __USER_DS 是为了支持从用户态访问内存的场景(如系统调用参数传递)。
3.1.2.RESTORE_ALL

RESTORE_INT_REGS

#define RESTORE_INT_REGS \popl %ebx;	\popl %ecx;	\popl %edx;	\popl %esi;	\popl %edi;	\popl %ebp;	\popl %eax

从栈中恢复通用整数寄存器(ebx, ecx, edx, esi, edi, ebp, eax)。

RESTORE_REGS

#define RESTORE_REGS	\RESTORE_INT_REGS; \
1:	popl %ds;	\
2:	popl %es;	\
.section .fixup,"ax";	\
3:	movl $0,(%esp);	\jmp 1b;		\
4:	movl $0,(%esp);	\jmp 2b;		\
.previous;		\
.section __ex_table,"a";\.align 4;	\.long 1b,3b;	\.long 2b,4b;	\
.previous
  • 功能:在 RESTORE_INT_REGS 基础上,额外恢复段寄存器(ds, es)。
  • 关键部分
    • 段寄存器恢复popl %dspopl %es 可能触发异常(如无效段选择子)。
    • 异常处理
      • .fixup:定义异常修复代码(将栈顶值设为 0,跳过出错的 pop 指令)。
      • __ex_table:异常表,记录可能出错的指令地址(1b, 2b)和对应的修复代码(3b, 4b)。
  • 机制
    • popl %ds 失败,CPU 会触发异常,内核通过 __ex_table 跳转到 3b,将栈顶(%esp 指向的值)设为 0(避免后续 pop 继续出错),然后跳回 1b 下一条指令(即 popl %es)。
    • 同理处理 popl %es 的异常。

RESTORE_ALL

#define RESTORE_ALL	\RESTORE_REGS	\addl $4, %esp;	\
1:	iret;		\
.section .fixup,"ax";   \
2:	sti;		\movl $(__USER_DS), %edx; \movl %edx, %ds; \movl %edx, %es; \movl $11,%eax;	\call do_exit;	\
.previous;		\
.section __ex_table,"a";\.align 4;	\.long 1b,2b;	\
.previous
  • 功能:恢复所有寄存器(包括 RESTORE_REGS)并执行 iret 返回用户态。
  • 关键部分
    • addl $4, %esp:跳过栈中的错误码(某些异常会压入错误码,如缺页异常)。
    • iret:从中断返回
    • 异常处理
      • iret失败,跳转到2b的修复代码:
        1. sti:允许中断(避免死锁)。
        2. 恢复段寄存器:将 dses 设为用户态数据段(__USER_DS)。
        3. 调用 do_exit:终止进程(eax=11 可能是信号编号或错误码)。
      • __ex_table:记录 iret 的地址(1b)和修复代码(2b)。

4. 核心机制解析

4.1.异常表(__ex_table

  • 作用:将可能出错的指令地址映射到修复代码,实现内核的“异常安全”。

  • 格式

    .long <出错指令地址>, <修复代码地址>
    
  • 流程

    1. CPU 执行出错指令(如 popl %ds)。
    2. 内核通过 __ex_table 找到修复代码(如 3b)。
    3. 执行修复逻辑(如跳过错误指令)。

4.2..fixup

  • 作用:存储修复代码,标记为可执行("ax" 表示分配+可执行)。
  • 修复逻辑
    • 对于 popl %ds 失败:将栈顶值设为 0(避免后续 pop 继续出错)。
    • 对于 iret 失败:恢复段寄存器并退出进程。

5.从fork系统调用返回用户空间

ENTRY(ret_from_fork)pushl %eaxcall schedule_tailGET_THREAD_INFO(%ebp)popl %eaxjmp syscall_exit

这个代码片段处理新创建的子进程在完成fork后,如何正确返回到用户空间继续执行。

5.1. 入口标签

ENTRY(ret_from_fork)
  • 定义函数入口点ret_from_fork 是子进程开始执行的地方
  • 调用场景:当 fork() 系统调用创建新进程后,子进程从这里开始执行

5.2. 保存系统调用返回值

pushl %eax
  • 保存eax寄存器:将eax的值压栈保护
  • eax的作用:在系统调用中,eax存放返回值。对于fork:
    • 父进程:eax = 子进程的PID
    • 子进程:eax = 0

5.3. 调用调度尾处理

call schedule_tail
asmlinkage void schedule_tail(task_t *prev)__releases(rq->lock)
{finish_task_switch(prev);if (current->set_child_tid)put_user(current->pid, current->set_child_tid);
}

关键函数schedule_tail() 完成进程切换的清理工作:

  • 清理前一个任务的相关资源

5.4. 获取线程信息

GET_THREAD_INFO(%ebp)

宏展开:这个宏获取当前进程的 thread_info 结构

#define GET_THREAD_INFO(reg) \movl $-THREAD_SIZE, reg; \andl %esp, reg

$-THREAD_SIZE

  • 相当于~(THREAD_SIZE - 1),得到内核栈地址的掩码
  • 如果是4KB的栈,即0xFFFFE000

andl %esp, reg

  • 将栈地址和掩码相与,可以得到栈的基地址,即thread_info结构地址

  • 结果ebp寄存器指向当前进程的thread_info结构

5.5. 恢复系统调用返回值

popl %eax
  • 恢复eax:将之前压栈的系统调用返回值弹出
  • 对于子进程,eax = 0(fork的返回值)

5.6. 跳转到系统调用退出

jmp syscall_exit

最终跳转:进入通用的系统调用退出路径,包括:

  • 检查是否需要信号处理
  • 恢复用户空间寄存器
  • 执行 iret 指令返回用户空间

二、system_call系统调用进入

ENTRY(system_call)pushl %eax			# save orig_eaxSAVE_ALLGET_THREAD_INFO(%ebp)# system call tracing in operationtestb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)jnz syscall_trace_entrycmpl $(nr_syscalls), %eaxjae syscall_badsys
syscall_call:call *sys_call_table(,%eax,4)movl %eax,EAX(%esp)		# store the return value:

1.ENTRY宏的定义和作用

#define ENTRY(name) \.globl name; \ALIGN; \name:

2.代码详细解析

2.1.第一行:保存原始系统调用号

pushl %eax            # save orig_eax
  • %eax 包含系统调用号
  • 保存到栈上,因为后面会修改EAX

2.2.第二行:保存所有寄存器

SAVE_ALL

2.3.第三行:获取线程信息

GET_THREAD_INFO(%ebp)

GET_THREAD_INFO:获取当前线程的 thread_info

2.4.第四-五行:系统调用跟踪检查

testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
jnz syscall_trace_entry
  • 检查是否需要系统调用跟踪或审计
  • 如果需要,跳转到跟踪处理代码

2.5.第六-七行:系统调用号验证

cmpl $(nr_syscalls), %eax
jae syscall_badsys
  • 比较系统调用号是否超出范围
  • 如果超出,跳转到错误处理

2.6.第八-九行:调用系统调用处理函数

syscall_call:
call *sys_call_table(,%eax,4)
movl %eax,EAX(%esp)        # store the return value

关键操作

  • sys_call_table(,%eax,4):系统调用表基址 + EAX*4
  • call *...:间接调用对应的系统调用函数
  • movl %eax,EAX(%esp):保存返回值到栈上的pt_regs
ENTRY(sys_call_table).long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */.long sys_exit.long sys_fork.long sys_read.long sys_write.long sys_open		/* 5 */...

该表保存了指定系统调用号的函数地址,一个地址四个字节,所以4 x 系统调用号 + 系统调用表基址 就是要调用的函数地址

3.实际执行流程示例

普通系统调用:

1. 用户程序:mov eax, 1 (exit), int 0x80
2. 进入system_call:- push %eax, SAVE_ALL- GET_THREAD_INFO- 检查跟踪 → 不需要- 检查系统调用号 → 有效- call sys_exit- 保存返回值

被跟踪的系统调用:

1. strace附加到进程
2. 设置_TIF_SYSCALL_TRACE标志
3. 进入system_call:- 检查跟踪标志 → 设置- 跳转到syscall_trace_entry- 通知strace- 执行实际系统调用

三、syscall_exit系统调用退出

#define TI_flags 8 /* offsetof(struct thread_info, flags) */
#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
work_notifysig_v86:pushl %ecx			# save ti_flags for do_notify_resumecall save_v86_state		# %eax contains pt_regs pointerpopl %ecxmovl %eax, %espxorl %edx, %edxcall do_notify_resumejmp restore_all
work_notifysig:				# deal with pending signals and# notify-resume requeststestl $VM_MASK, EFLAGS(%esp)movl %esp, %eaxjne work_notifysig_v86		# returning to kernel-space or# vm86-spacexorl %edx, %edxcall do_notify_resumejmp restore_all
work_pending:testb $_TIF_NEED_RESCHED, %cljz work_notifysig
ENTRY(resume_userspace)cli				# make sure we don't miss an interrupt# setting need_resched or sigpending# between sampling and the iretmovl TI_flags(%ebp), %ecxandl $_TIF_WORK_MASK, %ecx	# is there any work to be done on# int/exception return?jne work_pendingjmp restore_all
syscall_exit_work:testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cljz work_pendingsti				# could let do_syscall_trace() call# schedule() insteadmovl %esp, %eaxmovl $1, %edxcall do_syscall_tracejmp resume_userspace
syscall_exit:cli				# make sure we don't miss an interrupt# setting need_resched or sigpending# between sampling and the iretmovl TI_flags(%ebp), %ecxtestw $_TIF_ALLWORK_MASK, %cx	# current->workjne syscall_exit_work

1.代码流程解析

1.1.入口点:syscall_exit

syscall_exit:cli                         # 禁用中断movl TI_flags(%ebp), %ecx   # 加载线程标志到ECXtestw $_TIF_ALLWORK_MASK, %cx # 检查是否有工作需要做jne syscall_exit_work       # 有工作,跳转到工作处理# 否则直接恢复执行

1.2.系统调用工作处理:syscall_exit_work

syscall_exit_work:testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cljz work_pending             # 没有跟踪/审计/单步,跳转到通用工作sti                         # 启用中断(允许调度)movl %esp, %eax            # 传递pt_regs指针movl $1, %edx              # entryexit=1(系统调用退出)call do_syscall_trace      # 处理系统调用跟踪jmp resume_userspace       # 返回用户空间检查

1.3.通用工作调度:work_pending

work_pending:testb $_TIF_NEED_RESCHED, %cl  # 检查是否需要重新调度jz work_notifysig              # 不需要调度,处理信号# 需要调度时会调用schedule()

1.4.信号通知处理:work_notifysig

work_notifysig:testl $VM_MASK, EFLAGS(%esp)   # 检查是否从VM86模式返回movl %esp, %eaxjne work_notifysig_v86         # VM86模式,特殊处理xorl %edx, %edx               # oldset = NULLcall do_notify_resume         # 处理信号和通知jmp restore_all               # 恢复执行

1.5.VM86模式特殊处理:work_notifysig_v86

work_notifysig_v86:pushl %ecx                    # 保存线程标志call save_v86_state           # 保存VM86状态,返回pt_regspopl %ecx                     # 恢复线程标志movl %eax, %esp               # 使用新的栈指针xorl %edx, %edx               # oldset = NULLcall do_notify_resume         # 处理信号和通知jmp restore_all               # 恢复执行

1.6.用户空间恢复:resume_userspace

ENTRY(resume_userspace)cli                          # 禁用中断movl TI_flags(%ebp), %ecx    # 重新加载线程标志andl $_TIF_WORK_MASK, %ecx   # 检查工作掩码jne work_pending             # 有工作,继续处理jmp restore_all              # 没有工作,恢复执行

2.完整的执行流程

2.1.场景1:普通系统调用(无特殊工作)

1. syscall_exit:- 检查TIF_ALLWORK_MASK → 无工作- 直接restore_all返回用户空间

2.2.场景2:系统调用跟踪(strace

1. syscall_exit:- 检查TIF_ALLWORK_MASK → 有工作
2. syscall_exit_work:- 检查TIF_SYSCALL_TRACE → 设置- 调用do_syscall_trace(regs, 1)- 跳转到resume_userspace
3. resume_userspace:- 重新检查工作标志- 如果没有其他工作,restore_all

2.3.场景3:信号递送

1. syscall_exit:- 检查TIF_ALLWORK_MASK → 有工作
2. syscall_exit_work:- 检查跟踪标志 → 未设置- 跳转到work_pending
3. work_pending:- 检查TIF_NEED_RESCHED → 未设置- 跳转到work_notifysig
4. work_notifysig:- 检查VM86模式 → 不是- 调用do_notify_resume(regs, NULL, flags)- restore_all返回用户空间

四、VM86状态保存save_v86_state

struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
{struct tss_struct *tss;struct pt_regs *ret;unsigned long tmp;/** This gets called from entry.S with interrupts disabled, but* from process context. Enable interrupts here, before trying* to access user space.*/local_irq_enable();if (!current->thread.vm86_info) {printk("no vm86_info: BAD\n");do_exit(SIGSEGV);}set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);tmp = copy_to_user(&current->thread.vm86_info->regs,regs, VM86_REGS_SIZE1);tmp += copy_to_user(&current->thread.vm86_info->regs.VM86_REGS_PART2,&regs->VM86_REGS_PART2, VM86_REGS_SIZE2);tmp += put_user(current->thread.screen_bitmap,&current->thread.vm86_info->screen_bitmap);if (tmp) {printk("vm86: could not access userspace vm86_info\n");do_exit(SIGSEGV);}tss = &per_cpu(init_tss, get_cpu());current->thread.esp0 = current->thread.saved_esp0;current->thread.sysenter_cs = __KERNEL_CS;load_esp0(tss, &current->thread);current->thread.saved_esp0 = 0;put_cpu();loadsegment(fs, current->thread.saved_fs);loadsegment(gs, current->thread.saved_gs);ret = KVM86->regs32;return ret;
}

1.函数功能

save_v86_state() 负责从虚拟8086模式切换回保护模式,并保存VM86状态到用户空间

2.背景:虚拟8086模式(VM86)

什么是VM86模式?

  • x86处理器的一种特殊模式
  • 允许在保护模式下运行实模式(8086)程序
  • 用于DOS模拟器、16位应用程序兼容性

VM86 vs 保护模式:

特性VM86模式保护模式
内存访问1MB实模式4GB保护模式
特权级环3(用户态)环0-3
分段64KB段4GB段
用途16位程序32/64位程序

3.函数详细解析

3.1.第一阶段:启用中断并检查状态

local_irq_enable();if (!current->thread.vm86_info) {printk("no vm86_info: BAD\n");do_exit(SIGSEGV);
}

关键操作

  • local_irq_enable():启用中断(在entry.S中中断被禁用)
  • 检查vm86_info:确保有有效的VM86上下文结构
  • 如果没有,进程终止(SIGSEGV)

3.2.第二阶段:保存标志寄存器

set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);

标志处理

  • VEFLAGS:VM86有效的标志位
  • VIF_MASK:虚拟中断标志
  • v86mask:进程特定的VM86掩码
  • 作用:过滤和保存相关的EFLAGS位

3.3.第三阶段:复制寄存器状态到用户空间

tmp = copy_to_user(&current->thread.vm86_info->regs, regs, VM86_REGS_SIZE1);
tmp += copy_to_user(&current->thread.vm86_info->regs.VM86_REGS_PART2,&regs->VM86_REGS_PART2, VM86_REGS_SIZE2);
tmp += put_user(current->thread.screen_bitmap, &current->thread.vm86_info->screen_bitmap);
if (tmp) {printk("vm86: could not access userspace vm86_info\n");do_exit(SIGSEGV);
}

错误处理:如果复制到用户空间失败,终止进程。

3.4.第四阶段:恢复保护模式栈

tss = &per_cpu(init_tss, get_cpu());
current->thread.esp0 = current->thread.saved_esp0;
current->thread.sysenter_cs = __KERNEL_CS;
load_esp0(tss, &current->thread);
current->thread.saved_esp0 = 0;
put_cpu();

TSS(任务状态段)操作:

  • init_tss:每CPU的TSS结构
  • esp0:环0栈指针(内核栈)
  • saved_esp0:保存的保护模式栈指针
  • load_esp0():更新TSS中的ESP0字段

作用:从VM86栈切换回正常的保护模式内核栈

3.5.第五阶段:恢复段寄存器

loadsegment(fs, current->thread.saved_fs);
loadsegment(gs, current->thread.saved_gs);

段寄存器恢复

  • 在VM86模式中,FS/GS可能被修改
  • 恢复为保护模式的值
  • 确保正常的内存访问

3.6.第六阶段:返回保护模式寄存器状态

ret = KVM86->regs32;
return ret;

KVM86结构:内核内部的VM86管理结构,包含保护模式的寄存器状态

4.完整的VM86切换流程

4.1.进入VM86模式:

1. 用户程序调用vm86()系统调用
2. 内核设置VM86环境:- 保存保护模式寄存器- 设置VM86段描述符- 初始化VM86信息结构
3. 切换到VM86模式执行16位代码

4.2.退出VM86模式(本函数):

1. VM86程序触发异常或中断
2. 进入内核VM86处理程序
3. 调用save_v86_state():- 保存VM86寄存器状态到用户空间- 恢复保护模式栈和段寄存器- 返回保护模式寄存器状态
4. 继续正常的保护模式执行

五、系统调用跟踪和审计do_syscall_trace

__attribute__((regparm(3)))
void do_syscall_trace(struct pt_regs *regs, int entryexit)
{if (unlikely(current->audit_context)) {if (!entryexit)audit_syscall_entry(current, regs->orig_eax,regs->ebx, regs->ecx,regs->edx, regs->esi);elseaudit_syscall_exit(current, regs->eax);}if (!test_thread_flag(TIF_SYSCALL_TRACE) &&!test_thread_flag(TIF_SINGLESTEP))return;if (!(current->ptrace & PT_PTRACED))return;/* the 0x80 provides a way for the tracing parent to distinguishbetween a syscall stop and SIGTRAP delivery */ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));/** this isn't the same as continuing with a signal, but it will do* for normal use.  strace only continues with a signal if the* stopping signal is not SIGTRAP.  -brl*/if (current->exit_code) {send_sig(current->exit_code, current, 1);current->exit_code = 0;}
}

1.函数属性解析

__attribute__((regparm(3)))

x86性能优化

  • 前3个参数通过寄存器传递(EAX, EDX, ECX)
  • 减少栈操作,提高性能

2.函数参数

void do_syscall_trace(struct pt_regs *regs, int entryexit)
  • regs:包含系统调用参数的寄存器状态
  • entryexit:0=系统调用入口,1=系统调用出口

3.函数详细解析

3.1.第一阶段:系统调用审计

if (unlikely(current->audit_context)) {if (!entryexit)audit_syscall_entry(current, regs->orig_eax,regs->ebx, regs->ecx,regs->edx, regs->esi);elseaudit_syscall_exit(current, regs->eax);
}

审计子系统:

  • current->audit_context:进程的审计上下文

入口审计entryexit=0):

  • 系统调用号:regs->orig_eax
  • 参数:ebx, ecx, edx, esi(x86系统调用参数)

出口审计entryexit=1):

  • 返回值:regs->eax

3.2.第二阶段:跟踪条件检查

if (!test_thread_flag(TIF_SYSCALL_TRACE) &&!test_thread_flag(TIF_SINGLESTEP))return;
if (!(current->ptrace & PT_PTRACED))return;

跟踪标志:

  • TIF_SYSCALL_TRACE:系统调用跟踪启用
  • TIF_SINGLESTEP:单步调试启用
  • PT_PTRACED:进程被ptrace跟踪

快速返回:如果没有启用跟踪,立即返回避免性能损失。

3.3.第三阶段:通知调试器

ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&!test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));

条件分析

  • PT_TRACESYSGOOD:调试器要求区分系统调用陷阱和普通SIGTRAP
  • !TIF_SINGLESTEP:不是单步调试模式
  • 结果:如果条件满足,信号值 = SIGTRAP | 0x80

设计目的:

  • 普通SIGTRAP:信号值 = 5
  • 系统调用SIGTRAP:信号值 = 133 (5 | 0x80)
  • 帮助调试器区分不同类型的停止

3.4.第四阶段:处理退出代码

if (current->exit_code) {send_sig(current->exit_code, current, 1);current->exit_code = 0;
}

退出代码机制:

  • current->exit_code:调试器设置的信号编号
  • 当调试器希望进程继续执行但附带一个信号时使用

4.完整工作流程

4.1.场景1:strace系统调用跟踪

1. strace attach到目标进程
2. 设置 TIF_SYSCALL_TRACE 和 PT_PTRACED
3. 目标进程执行系统调用:- 入口:do_syscall_trace(regs, 0)→ 审计记录(如果有)→ 通知strace:SIGTRAP|0x80→ strace显示系统调用和参数- 执行系统调用- 出口:do_syscall_trace(regs, 1)→ 审计记录返回值→ 通知strace:SIGTRAP|0x80→ strace显示返回值

4.2.场景2:GDB单步调试

1. GDB单步执行
2. 设置 TIF_SINGLESTEP 和 PT_PTRACED
3. 遇到系统调用:- 入口:do_syscall_trace(regs, 0)→ 通知GDB:普通SIGTRAP(无0x80)- GDB显示汇编指令- 用户单步继续
http://www.dtcms.com/a/446778.html

相关文章:

  • 备案 网站名称 修改河北建设安装工程有限公司怎么样
  • 【2026计算机毕业设计】基于jsp的药店管理系统
  • 做的网站在百度找不到wordpress网页排版插件
  • 【高并发服务器】二、时间轮定时器设计与实现
  • 【操作系统】多线程
  • 信阳seo优化seo有些什么关键词
  • Giants Shoulder - Hyrix: LPDDR5 Commands New Features
  • 有关网站建设的外文文献好习惯网站
  • 网站的内容与功能设计优书网所有书单
  • 小迪web自用笔记56
  • Spring Security 完整使用指南
  • 中咨城建设计有限公司 网站网站seo外链接
  • 什么样的网站利于优化上海外贸公司集中在哪里
  • app与手机网站门户网站建设制作
  • 电竞网站方案设计河北邯郸网络科技有限公司
  • 天津大学 2025 预推免 第二批 机试 题解
  • 中山市城市建设档案馆网站wordpress dux 高亮
  • 免费空间做淘宝客网站wordpress收缩
  • 海报模板免费网站做阿里云网站空间
  • 深度特征工程实战:从数据到模型的关键一步
  • 帮人做网站怎么收费微信管理平台登录
  • 国外网站建设接单韩国做游戏的电影 迅雷下载网站有哪些
  • 哪些网站是phpwind做的国内wordpress有名主题
  • asp做网站教程强大的网站设计制作
  • 中国建设银行网站 纪念币预约企业网址下载
  • xfreerdp 使用指南:FreeRDP 客户端详解与 RDP 协议深度解析
  • 深圳高端网站设计开发企业系统工程
  • RK3588:MIPI底层驱动学习——入门第四篇(驱动精华:OV13855驱动加载时究竟发生了什么?)
  • 太原做网站 小程序工业和信息化部网站备案系统是什么意思
  • 详解指针1