Linux kernel signal原理(下)- aarch64架構sigreturn流程

一、前言

? ? ? ?在上篇中寫到了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.pswp.cn/bicheng/78458.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/78458.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/78458.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華為OD機試真題——簡易內存池(2025A卷:200分)Java/python/JavaScript/C++/C/GO最佳實現

2025 A卷 200分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析&#xff1b; 并提供Java、python、JavaScript、C、C語言、GO六種語言的最佳實現方式&#xff01; 本文收錄于專欄&#xff1a;《2025華為OD真題目錄全流程解析/備考攻略/經驗…

騰訊一面面經:總結一下

1. Java 中的 和 equals 有什么區別&#xff1f;比較對象時使用哪一個 1. 操作符&#xff1a; 用于比較對象的內存地址&#xff08;引用是否相同&#xff09;。 對于基本數據類型、 比較的是值。&#xff08;8種基本數據類型&#xff09;對于引用數據類型、 比較的是兩個引…

計算機網絡中的DHCP是什么呀? 詳情解答

目錄 DHCP 是什么&#xff1f; DHCP 的工作原理 主要功能 DHCP 與網絡安全的關系 1. 正面作用 2. 潛在安全風險 DHCP 的已知漏洞 1. 協議設計缺陷 2. 軟件實現漏洞 3. 配置錯誤導致的漏洞 4. 已知漏洞總結 舉例說明 DHCP 與網絡安全 如何提升 DHCP 安全性 總結 D…

2025 年導游證報考條件新政策解讀與應對策略

2025 年導游證報考政策有了不少新變化&#xff0c;這些變化會對報考者產生哪些影響&#xff1f;我們又該如何應對&#xff1f;下面就為大家詳細解讀新政策&#xff0c;并提供實用的應對策略。 最引人注目的變化當屬中職旅游類專業學生的報考政策。以往&#xff0c;中專學歷報考…

【物聯網】基于LORA組網的遠程環境監測系統設計(ThingsCloud云平臺版)

演示視頻: 基于LORA組網的遠程環境監測系統設計(ThingsCloud云平臺版) 前言:本設計是基于ThingsCloud云平臺版,還有另外一個版本是基于機智云平臺版本,兩個設計只是云平臺和手機APP的區別,其他功能都一樣。如下鏈接: 【物聯網】基于LORA組網的遠程環境監測系統設計(機…

SQL 函數進行左邊自動補位fnPadLeft和FORMAT

目錄 1.問題 2.解決 方式1 方式2 3.結果 1.問題 例如在SQL存儲過程中&#xff0c;將1 或10 或 100 長度不足的時候&#xff0c;自動補足長度。 例如 1 → 001 10→ 010 100→100 2.解決 方式1 SELECT FORMAT (1, 000) AS FormattedNum; SELECT FORMAT(12, 000) AS Form…

Nacos簡介—2.Nacos的原理簡介

大綱 1.Nacos集群模式的數據寫入存儲與讀取問題 2.基于Distro協議在啟動后的運行規則 3.基于Distro協議在處理服務實例注冊時的寫路由 4.由于寫路由造成的數據分片以及隨機讀問題 5.寫路由 數據分區 讀路由的CP方案分析 6.基于Distro協議的定時同步機制 7.基于Distro協…

中電金信聯合阿里云推出智能陪練Agent

在金融業加速數智化轉型的今天&#xff0c;提升服務效率與改善用戶體驗已成為行業升級的核心方向。面對這一趨勢&#xff0c;智能體與智能陪練的結合應用&#xff0c;正幫助金融機構突破傳統業務模式&#xff0c;開拓更具競爭力的創新機遇。 在近日召開的阿里云AI勢能大會期間&…

十分鐘恢復服務器攻擊——群聯AI云防護系統實戰

場景描述 服務器遭遇大規模DDoS攻擊&#xff0c;導致服務不可用。通過群聯AI云防護系統的分布式節點和智能調度功能&#xff0c;快速切換流量至安全節點&#xff0c;清洗惡意流量&#xff0c;10分鐘內恢復業務。 技術實現步驟 1. 啟用智能調度API觸發節點切換 群聯系統提供RE…

LLM量化技術全景:GPTQ、QAT、AWQ、GGUF與GGML

01 引言 本文介紹的是在 LLM 討論中經常聽到的各種量化技術。本文的目的是提供一步一步的解釋和代碼&#xff0c;讓大家可以自己使用這些技術來壓縮模型。 閑話少說&#xff0c;我們來研究一下吧&#xff01; 02 Quantization 量化是指將高精度數字轉換為低精度數字。低精…

IP的基礎知識以及相關機制

IP地址 1.IP地址的概念 IP地址是分配給連接到互聯網或局域網中的每一個設備的唯一標識符 也就是說IP地址是你設備在網絡中的定位~ 2.IP版本~ IP版本分為IPv4和IPv6&#xff0c;目前我們最常用的還是IPv4~~但是IPv4有個缺點就是地址到現在為止&#xff0c;已經接近枯竭~~&…

本地使用Ollama部署DeepSeek

以下是在本地使用Ollama部署DeepSeek的詳細教程&#xff0c;涵蓋安裝、修改安裝目錄、安裝大模型以及刪除大模型的操作步驟。 安裝Ollama 1. 系統要求 確保你的系統滿足以下條件&#xff1a; 操作系統&#xff1a;macOS、Linux或者Windows。足夠的磁盤空間和內存。 2. 安裝…

開源項目實戰學習之YOLO11:ultralytics-cfg-datasets-Objects365、open-images-v7.yaml文件(六)

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 medical - pills.yaml 通常用于配置與醫學藥丸檢測任務相關的參數和信息 Objects365.yaml 用于配置與 Objects365 數據集相關信息的文件。Objects365 數據集包含 365 個不同的物體類別…

23種設計模式-行為型模式之策略模式(Java版本)

Java 策略模式&#xff08;Strategy Pattern&#xff09;詳解 &#x1f9e0; 什么是策略模式&#xff1f; 策略模式是一種行為型設計模式&#xff0c;它定義了一系列算法&#xff0c;把它們一個個封裝起來&#xff0c;并且使它們可以互相替換。策略模式讓算法獨立于使用它的客…

使用 AI Agent 改善師生互動的設計文檔

使用 AI Agent 改善師生互動的設計文檔 一、引言 1.1 研究背景 當前教育領域的師生互動存在諸多挑戰&#xff0c;如教師負擔過重、學生個體差異大導致難以滿足所有人的需求&#xff0c;以及信息傳遞延遲等問題。引入AI-Agent能夠有效緩解這些問題&#xff0c;通過自動化手段協…

2、Ubuntu 環境下安裝RabbitMQ

?. 安裝Erlang RabbitMqRabbitMq需要Erlang語?的?持&#xff0c;在安裝rabbitMq之前需要安裝erlang需要Erlang語?的?持&#xff0c;在安裝rabitMq之前需要安裝erlang。 安裝erlang # 更新軟件包 sudo apt-get update # 安裝 erlang sudo apt-get install erlang 查看er…

Node.js 操作 ElasticSearch 完整指南:從安裝到實戰

本文將手把手教你如何搭建 ElasticSearch 環境&#xff0c;并通過 Node.js 實現高效數據檢索。包含 10 個可直接復用的代碼片段&#xff0c;助你快速掌握搜索、聚合等核心功能&#xff01; 環境搭建篇 1. ElasticSearch 安裝要點 下載 es下載連接 下載下來后&#xff0c;進…

硬核科普丨2025年安全、高效網絡準入控制系統深度解析

陽途網絡準入控制系統&#xff08;Network Access Control&#xff0c;簡稱NAC&#xff09;是當代網絡安全領域的重要工具&#xff0c;有效防止未經授權的訪問和數據泄露&#xff0c;保障網絡資源的安全性和完整性。本文將深入探討陽途網絡準入控制系統的的重要性和作用。 一、…

搜索二叉樹-key的搜索模型

二叉搜索樹(Binary Search Tree, BST)是一種重要的數據結構&#xff0c;它有兩種基本模型&#xff1a;Key模型和Key/Value模型。 一、Key模型 1.基本概念 Key模型是二叉搜索樹中最簡單的形式&#xff0c;每個節點只存儲一個鍵值(key)&#xff0c;沒有額外的數據值(value)。這…

安卓四大組件之ContentProvider

目錄 實現步驟 代碼分析 onCreate insert query ContextHolder Cursor 作用與用法 基本步驟&#xff1a; 可能的面試題&#xff1a;為什么使用Cursor&#xff1f; 為什么使用Cursor 使用Cursor的好處 靜態內部類實現單例模式 AnndroidManifest.xml配置信息 注釋的…