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

所有网站302跳转百度可信赖的郑州网站建设

所有网站302跳转百度,可信赖的郑州网站建设,什么是平面设计 都包括哪些内容,变更网站怎么做一、前言 在上篇中写到了linux中signal的处理流程,在do_signal信号处理的流程最后,会通过sigreturn再次回到线程现场,上篇文章中介绍了在X86_64架构下的实现,本篇中介绍下在aarch64架构下的实现原理。 二、sigaction系统调用 #i…

一、前言

       在上篇中写到了linux中signal的处理流程,在do_signal信号处理的流程最后,会通过sigreturn再次回到线程现场,上篇文章中介绍了在X86_64架构下的实现,本篇中介绍下在aarch64架构下的实现原理。

二、sigaction系统调用

#include <signal.h>
#include <stdio.h>
#include <string.h>void signal_handler(int signum, siginfo_t *siginfo, void *context)
{printf("Received signal %d\n", signum);printf("Send by PID: %d\n", siginfo->si_pid);
}int main()
{struct sigaction act;memset(&act, 0, sizeof(act));act.sa_sigaction = signal_handler;act.sa_flags = SA_SIGINFO;if (sigaction(SIGTERM, &act, NULL) < 0) {perror("sigaction");return 1;}while (1) {printf("perfect\n");sleep(10);}return 0;
}

如上是使用sigaction系统调用做的一个简单的测试。

1、放到环境上,并使用strace跟踪进程的系统调用。strace ./test_siginfo
2、向该进程发送SIGTERM信号

可以看到用户态进程在处理SIGTERM信号之后,通过特殊的rt_sigreturn系统调用到内核之后,又再次返回到用户态执行。具体这个rt_sigreturn从哪里来的,下面分析下。

首先看了下glibc的源码,看下在注册sigaction函数的时候是否会把sigreturn系统调用也注册进去,通过阅读源码发现x86_64是采用这个方式实现的,但是aarch64不是。

 

有事就找man,通过看了下man 2 sigreturn,看到了如下关键信息:

怀疑aarch64 架构下是通过vdso实现的。

三、sigreturn实现流程

通过查看上述测试进程在/proc下的内存映射,如下所示:

sh-5.0# cat /proc/974770/maps 
00400000-00401000 r-xp 00000000 b3:07 255                                /data/test_siginfo
00410000-00411000 r--p 00000000 b3:07 255                                /data/test_siginfo
00411000-00412000 rw-p 00001000 b3:07 255                                /data/test_siginfo
06801000-06822000 rw-p 00000000 00:00 0                                  [heap]
7f94c28000-7f94d81000 r-xp 00000000 b3:01 424154                         /usr/lib/aarch64-linux-gnu/libc-2.31.so
7f94d81000-7f94d90000 ---p 00159000 b3:01 424154                         /usr/lib/aarch64-linux-gnu/libc-2.31.so
7f94d90000-7f94d93000 r--p 00158000 b3:01 424154                         /usr/lib/aarch64-linux-gnu/libc-2.31.so
7f94d93000-7f94d96000 rw-p 0015b000 b3:01 424154                         /usr/lib/aarch64-linux-gnu/libc-2.31.so
7f94d96000-7f94d99000 rw-p 00000000 00:00 0 
7f94da7000-7f94dac000 r-xp 00000000 b3:01 42742                          /usr/lib64/libpsh_essence.so
7f94dac000-7f94dbb000 ---p 00005000 b3:01 42742                          /usr/lib64/libpsh_essence.so
7f94dbb000-7f94dbc000 r--p 00004000 b3:01 42742                          /usr/lib64/libpsh_essence.so
7f94dbc000-7f94dbd000 rw-p 00005000 b3:01 42742                          /usr/lib64/libpsh_essence.so
7f94dbd000-7f94dde000 r-xp 00000000 b3:01 423760                         /usr/lib/aarch64-linux-gnu/ld-2.31.so
7f94de6000-7f94dea000 rw-p 00000000 00:00 0 
7f94deb000-7f94ded000 r--p 00000000 00:00 0                              [vvar]
7f94ded000-7f94dee000 r-xp 00000000 00:00 0                              [vdso]
7f94dee000-7f94def000 r--p 00021000 b3:01 423760                         /usr/lib/aarch64-linux-gnu/ld-2.31.so
7f94def000-7f94df1000 rw-p 00022000 b3:01 423760                         /usr/lib/aarch64-linux-gnu/ld-2.31.so
7feceb1000-7feced2000 rw-p 00000000 00:00 0                              [stack]

 其中:

7f94ded000-7f94dee000 r-xp 00000000 00:00 0                              [vdso]

可以看到vdso内存大小:0x1000 = 4096,即一个page的大小。

vdso的起始虚拟地址在进程974770是: 7f94ded000,转化为十进制即547958476800,将这段内存dump到文件中:

sh-5.0# dd if=/proc/974770/mem of=/tmp/linus-vdso.so skip=547958476800 ibs=1 count=4096
dd: /proc/974770/mem: cannot skip to specified offset
4096+0 records in
8+0 records out
4096 bytes (4.1 kB, 4.0 KiB) copied, 0.0178463 s, 230 kB/s

 由于vdso是一个完整的ELF镜像,可以对其进行符号查找:

sh-5.0# objdump -T /tmp/linus-vdso.so /tmp/linus-vdso.so:     file format elf64-littleaarch64DYNAMIC SYMBOL TABLE:
0000000000000000 g    DO ABS  0000000000000000  LINUX_2.6.39 LINUX_2.6.39
0000000000000750 g    DF .text  0000000000000078  LINUX_2.6.39 __kernel_clock_getres
00000000000007cc g    D  .text  0000000000000008  LINUX_2.6.39 __kernel_rt_sigreturn
00000000000005a0 g    DF .text  00000000000001b0  LINUX_2.6.39 __kernel_gettimeofday
0000000000000300 g    DF .text  00000000000002a0  LINUX_2.6.39 __kernel_clock_gettime

从符号表中可以看出,确实是有__kernel_rt_sigreturn的实现。

下面看下内核是如何实现的:

 通过阅读内核源码,handle_signal的实现在构建用户态栈帧的时候可以看到如下关键流程:

static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,struct pt_regs *regs)
{struct rt_sigframe_user_layout user;struct rt_sigframe __user *frame;int err = 0;fpsimd_signal_preserve_current_state();if (get_sigframe(&user, ksig, regs))return 1;frame = user.sigframe;__put_user_error(0, &frame->uc.uc_flags, err);__put_user_error(NULL, &frame->uc.uc_link, err);err |= __save_altstack(&frame->uc.uc_stack, regs->sp);err |= setup_sigframe(&user, regs, set);if (err == 0) {setup_return(regs, &ksig->ka, &user, usig);  //信号返回关键函数if (ksig->ka.sa.sa_flags & SA_SIGINFO) { //如果注册的时候传入了SA_SIGINFO标记,就会把X1,X2寄存器值传给用户态回调err |= copy_siginfo_to_user(&frame->info, &ksig->info);regs->regs[1] = (unsigned long)&frame->info; //X1regs->regs[2] = (unsigned long)&frame->uc;   //X2}}return err;
}
static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,struct rt_sigframe_user_layout *user, int usig)
{__sigrestore_t sigtramp;regs->regs[0] = usig;regs->sp = (unsigned long)user->sigframe;regs->regs[29] = (unsigned long)&user->next_frame->fp;regs->pc = (unsigned long)ka->sa.sa_handler;/** Signal delivery is a (wacky) indirect function call in* userspace, so simulate the same setting of BTYPE as a BLR* <register containing the signal handler entry point>.* Signal delivery to a location in a PROT_BTI guarded page* that is not a function entry point will now trigger a* SIGILL in userspace.** If the signal handler entry point is not in a PROT_BTI* guarded page, this is harmless.*/if (system_supports_bti()) {regs->pstate &= ~PSR_BTYPE_MASK;regs->pstate |= PSR_BTYPE_C;}/* TCO (Tag Check Override) always cleared for signal handlers */regs->pstate &= ~PSR_TCO_BIT;if (ka->sa.sa_flags & SA_RESTORER)   //x86_64架构默认实现sigtramp = ka->sa.sa_restorer;elsesigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); //aarch_64架构实现方式regs->regs[30] = (unsigned long)sigtramp; //将sigreturn系统调用地址保存在X30寄存器中
}

 通过以上代码可以很清晰的看出在aarch64架构下的实现,即首先会在VDSO的符号表中找到sigreturn的地址,然后保存在X30寄存器中,X30寄存器保存的是函数的返回地址,即在用户态handler执行完成之后要执行的函数地址。对arm寄存器不熟悉的可以参考之前的文章:

ARM64架构栈帧以及帧指针FP-CSDN博客

整个流程可以归结如下图所示:

1、用户程序注册了处理函数signal_handler来捕获SIGTERM信号。

2、当前正在执行main函数时,若发生中断或异常导致切换到内核态。

3、在中断处理完成后,在返回用户态执行main函数之前,检测到有SIGTERM信号pending。

4、内核决定在返回用户态后,不恢复main函数的上下文继续执行,而是调用signal_handler函数。signal_handler函数和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程。

5、signal_handler函数执行完毕后,会自动执行特殊的系统调用sigreturn,再次进入内核态。

6、如果没有新的信号pending,此次返回用户态将会恢复main函数的上下文,并继续执行。

http://www.dtcms.com/a/603509.html

相关文章:

  • 网站开发与网站建设甘肃兰州地震最新消息
  • 网站开发与推广计划书个人域名备案做企业网站
  • 重庆网站建设公司是什么意思小程序免费网站
  • 汇编语言编译器MASM | 高效编写汇编程序的工具
  • 网站设计步骤图片文字图片制作网站
  • 个人教程网站广西网站建设开发团队
  • 国内高端大气的网站设计wordpress 安装地址
  • 网站 mvc 设计网站开发图片放哪里
  • 江苏网站建设seo优化a站app
  • 自动优化网站建设wordpress 添加自定义字段
  • 深圳盐田住房和建设局网站广州企业100强
  • 网站文字怎么做超链接wordpress承载压力
  • 徐州网站建设开发企业网站建设平台的功能
  • 网站设计O2O平台佛山总代理国外商品网站
  • leetcode 2654
  • 停机问题与考拉兹猜想:循环何时终止
  • 网站建立的企业flash手机网站制作
  • 海外网站推广优化专员网站关于我们怎么做
  • 久久建筑网是个什么样的网站中文手机app开发软件
  • 旅游分析 网站制作电子商务网站
  • 中国建材网官方网站免费企业wordpress主题
  • 长沙营销型网站制如何做google推广
  • 惠州seo网站管理汕头百姓网二手车交易市场
  • 营销型网站建设方案演讲ppt用ps做零食网站模板
  • 网站开发具备知识有哪些网站开发代码
  • cocos 发布 安卓应用
  • 元素周期表:宇宙给人类的“积木说明书”
  • 网店美工设计seo 网站 结构
  • 兰州产品营销网站建设网站开发前台软件用什么
  • 北京网站建设laitang医院手机网站模板