哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

linux內(nèi)核信號是如何處理的?看完全懂了……

電子設計 ? 來源:互聯(lián)網(wǎng) ? 作者:佚名 ? 2017-11-16 05:11 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本文簡單介紹下Linux信號處理機制,為介紹二進制翻譯下信號處理機制做一個鋪墊。
本文主要參考書目《Linux內(nèi)核源代碼情景分析》《獨辟蹊徑品內(nèi)核:Linux內(nèi)核源代碼導讀》
首先,先說一下什么是信號。信號本質(zhì)上是在軟件層次上對中斷機制的一種模擬,其主要有以下幾種來源:

程序錯誤:除零,非法內(nèi)存訪問…

外部信號:終端Ctrl-C產(chǎn)生SGINT信號,定時器到期產(chǎn)生SIGALRM…

顯式請求:kill函數(shù)允許進程發(fā)送任何信號給其他進程或進程組。

在Linux下,可以通過以下命令查看系統(tǒng)所有的信號:

kill-l

可以通過類似下面的命令顯式的給一個進程發(fā)送一個信號:

kill-2pid

上面的命令將2號信號發(fā)送給進程id為pid的進程。不存在編號為0的信號。

目前Linux支持64種信號。信號分為非實時信號(不可靠信號)和實時信號(可靠信號)兩種類型,對應于 Linux 的信號值為 1-31 和 34-64。信號是異步的,一個進程不必通過任何操作來等待信號的到達,事實上,進程也不知道信號到底什么時候到達。本文著重于Linux的信號處理機制,對信號更多的介紹可以參考這里。

一般情況下一個進程接受到信號后,會有如下的行為:

進程對信號的響應

忽略信號:大部分信號可被忽略,除SIGSTOP和SIGKILL信號外(這是超級用戶殺掉或停掉任意進程的手段)。

捕獲信號:注冊信號處理函數(shù),它對產(chǎn)生的特定信號做處理。

讓信號默認動作起作用:unix內(nèi)核定義的默認動作,有5種情況:

a) 流產(chǎn)abort:終止進程并產(chǎn)生core文件。

b) 終止stop:終止進程但不生成core文件。

c) 忽略:忽略信號。

d) 掛起suspend:掛起進程。

e) 繼續(xù)continue:若進程是掛起的,則resume進程,否則忽略此信號。

注冊信號處理函數(shù)

如果想要進程捕獲某個信號,然后作出相應的處理,就需要注冊信號處理函數(shù)。同中斷類似,內(nèi)核也為每個進程準備了一個信號向量表,信號向量表中記錄著每個信號所對應的處理機制,默認情況下是調(diào)用默認處理機制。當進程為某個信號注冊了信號處理程序后,發(fā)生該信號時,內(nèi)核就會調(diào)用注冊的函數(shù)。

注冊信號處理函數(shù)是通過系統(tǒng)調(diào)用signal()、sigaction()。其中signal()在可靠信號系統(tǒng)調(diào)用的基礎上實現(xiàn), 是庫函數(shù)。它只有兩個參數(shù),不支持信號傳遞信息,主要是用于前32種非實時信號的安裝;而sigaction()是較新的函數(shù)(由兩個系統(tǒng)調(diào)用實 現(xiàn):sys_signal以及sys_rt_sigaction),有三個參數(shù),支持信號傳遞信息,主要用來與 sigqueue() 系統(tǒng)調(diào)用配合使用,當然,sigaction()同樣支持非實時信號的安裝。sigaction()優(yōu)于signal()主要體現(xiàn)在支持信號帶有參數(shù)。關于這方面的內(nèi)容,如果想獲取更多,也可參考這里。

Linux下信號處理機制

進程如何發(fā)現(xiàn)和接受信號?

我們知道,信號是異步的,一個進程不可能等待信號的到來,也不知道信號會到來,那么,進程是如何發(fā)現(xiàn)和接受信號呢?實際上,信號的接收不是由用戶進程來完成的,而是由內(nèi)核代理。當一個進程P2向另一個進程P1發(fā)送信號后,內(nèi)核接受到信號,并將其放在P1的信號隊列當中。當P1再次陷入內(nèi)核態(tài)時,會檢查信號隊列,并根據(jù)相應的信號調(diào)取相應的信號處理函數(shù)。如下圖所示:


其中,動作c:發(fā)現(xiàn)和捕捉信號

信號檢測和響應時機

剛才我們說,當P1再次陷入內(nèi)核時,會檢查信號隊列。那么,P1什么時候會再次陷入內(nèi)核呢?陷入內(nèi)核后在什么時機會檢測信號隊列呢?

當前進程由于系統(tǒng)調(diào)用、中斷或異常而進入系統(tǒng)空間以后,從系統(tǒng)空間返回到用戶空間的前夕。

當前進程在內(nèi)核中進入睡眠以后剛被喚醒的時候(必定是在系統(tǒng)調(diào)用中),或者由于不可忽略信號的存在而提前返回到用戶空間。

進入信號處理函數(shù)

發(fā)現(xiàn)信號后,根據(jù)信號向量,知道了處理函數(shù),那么該如何進入信號處理程序,又該如何返回呢?

我們知道,用戶進程提供的信號處理函數(shù)是在用戶態(tài)里的,而我們發(fā)現(xiàn)信號,找到信號處理函數(shù)的時刻處于內(nèi)核態(tài)中,所以我們需要從內(nèi)核態(tài)跑到用戶態(tài)去執(zhí)行信號處理程序,執(zhí)行完畢后還要返回內(nèi)核態(tài)。這個過程如下圖所示:

如圖中所見,處理信號的整個過程是這樣的:進程由于 系統(tǒng)調(diào)用或者中斷 進入內(nèi)核,完成相應任務返回用戶空間的前夕,檢查信號隊列,如果有信號,則根據(jù)信號向量表找到信號處理函數(shù),設置好“frame”后,跳到用戶態(tài)執(zhí)行信號處理函數(shù)。信號處理函數(shù)執(zhí)行完畢后,返回內(nèi)核態(tài),設置“frame”,再返回到用戶態(tài)繼續(xù)執(zhí)行程序。

在上面這段話中,我提到“frame”,frame是什么?那么為什么要設置frame?為什么在執(zhí)行完信號處理函數(shù)后還要返回內(nèi)核態(tài)呢?

什么叫Frame?

在調(diào)用一個子程序時,堆棧要往下(邏輯意義上是往上)伸展,這是因為需要在堆棧中保存子程序的返回地址,還因為子程序往往有局部變量,也要占用堆棧中的空間。此外,調(diào)用子程序時的參數(shù)也是在堆棧中。子程序調(diào)用嵌套越深,則堆棧伸展的層次也越多。在堆棧中的每一個這樣的層次,就稱為一個”框架”,即frame。

一般來說,當子程序和調(diào)用它的程序在同一空間中時,堆棧的伸展,也就是堆棧中框架的建立,過程主要如下:

call指令將返回地址壓入堆棧(自動)

用push指令壓入調(diào)用參數(shù)

調(diào)整堆棧指針來分配局部變量

為什么以及怎么設置frame?

我們知道,當進程陷入內(nèi)核態(tài)的時候,會在堆棧中保存中斷現(xiàn)場。因為用戶態(tài)和內(nèi)核態(tài)是兩個運行級別,所以要使用兩個不同的棧。當用戶進程通過系統(tǒng)調(diào)用剛進入內(nèi)核的時候,CPU會自動在該進程的內(nèi)核棧上壓入下圖所示的內(nèi)容:(圖來自《Linux內(nèi)核完全注釋》)

在處理完系統(tǒng)調(diào)用以后,就要調(diào)用do_signal()函數(shù)進行設置frame等工作。這時內(nèi)核堆棧的狀態(tài)應該跟下圖左半部分類似(系統(tǒng)調(diào)用將一些信息壓入棧了):

在找到了信號處理函數(shù)之后,do_signal函數(shù)首先把內(nèi)核堆棧中存放返回執(zhí)行點的eip保存為old_eip,然后將eip替換為信號處理函數(shù)的地址,然后將內(nèi)核中保存的“原ESP”(即用戶態(tài)棧地址)減去一定的值,目的是擴大用戶態(tài)的棧,然后將內(nèi)核棧上的內(nèi)容保存到用戶棧上,這個過程就是設置frame.值得注意的是下面兩點:

之所以把EIP的值設置成信號處理函數(shù)的地址,是因為一旦進程返回用戶態(tài),就要去執(zhí)行信號處理程序,所以EIP要指向信號處理程序而不是原來應該執(zhí)行的地址。

之所以要把frame從內(nèi)核??截惖接脩魲?,是因為進程從內(nèi)核態(tài)返回用戶態(tài)會清理這次調(diào)用所用到的內(nèi)核棧(類似函數(shù)調(diào)用),內(nèi)核棧又太小,不能單純的在棧上保存另一個frame(想象一下嵌套信號處理),而我們需要EAX(系統(tǒng)調(diào)用返回值)、EIP這些信息以便執(zhí)行完信號處理函數(shù)后能繼續(xù)執(zhí)行程序,所以把它們拷貝到用戶態(tài)棧以保存起來。

以上這些搞清楚之后,下面的事情就順利多了。這時進程返回用戶空間,就會根據(jù)內(nèi)核棧中的EIP值執(zhí)行信號處理函數(shù)。那么,信號處理程序執(zhí)行完后,怎么返回程序繼續(xù)執(zhí)行呢?

信號處理函數(shù)執(zhí)行完后怎么辦?

信號處理程序執(zhí)行完畢之后,進程會主動調(diào)用sigreturn()系統(tǒng)調(diào)用再次回到內(nèi)核,查看有沒有其他信號需要處理,如果沒有,這時內(nèi)核就會做一些善后工作,將之前保存的frame恢復到內(nèi)核棧,恢復eip的值為old_eip,然后返回用戶空間,程序就能夠繼續(xù)執(zhí)行。至此,內(nèi)核遍完成了一次(或幾次)信號處理工作。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    88

    文章

    11806

    瀏覽量

    219482
  • 數(shù)字信號處理

    關注

    16

    文章

    580

    瀏覽量

    47881
  • IP內(nèi)核
    +關注

    關注

    0

    文章

    13

    瀏覽量

    13150
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    如何理解Linux內(nèi)核中的PCIe驅(qū)動

    我們習慣了用 Verilog 去死磕 PCIe 的底層協(xié)議狀態(tài)機。但一旦越過硬件邊界來到操作系統(tǒng)層面,Linux 內(nèi)核是如何接管并驅(qū)動這些 PCI/PCIe 設備的呢?由于不同的 CPU 架構(gòu)實現(xiàn)了
    的頭像 發(fā)表于 04-11 17:22 ?1171次閱讀

    Linux內(nèi)核無法恢復怎么處理?

    將日志消息打印到 UART inresume_bl31會導致 Linux 內(nèi)核無法恢復。 static void resume_bl31(struct s32g_ssram_mailbox
    發(fā)表于 03-16 06:02

    Linux內(nèi)核驅(qū)動開發(fā)的技術(shù)核心精要

    嵌入式Linux驅(qū)動開發(fā)是連接硬件與操作系統(tǒng)的關鍵環(huán)節(jié)。隨著內(nèi)核演進(如Linux 6.13)和硬件復雜度提升,開發(fā)者需掌握并發(fā)控制、中斷分層、內(nèi)存管理、設備樹、調(diào)試工具等核心知識。本文提煉出驅(qū)動
    發(fā)表于 03-10 13:56

    Linux內(nèi)核的“心跳”:jiffies如何為系統(tǒng)計時?

    Linux 內(nèi)核的世界里,有一個默默工作的 "計時器"——jiffies。它不像我們手機上的時鐘那樣顯示年月日,卻掌控著內(nèi)核中絕大多數(shù)時間相關的操作:從進程調(diào)度到設備驅(qū)動的定時檢查,都離不開它的身影。
    的頭像 發(fā)表于 02-04 16:27 ?909次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的“心跳”:jiffies如何為系統(tǒng)計時?

    深入RK3588內(nèi)核:rockchip_linux_defconfig的作用與調(diào)試價值

    在 RK3588 芯片的 Linux 開發(fā)中,有一個文件始終是開發(fā)者繞不開的核心 ——kernel/arch/arm64/configs/rockchip_linux_defconfig。無論是首次
    的頭像 發(fā)表于 02-03 15:56 ?1347次閱讀
    深入RK3588<b class='flag-5'>內(nèi)核</b>:rockchip_<b class='flag-5'>linux</b>_defconfig的作用與調(diào)試價值

    Linux系統(tǒng)內(nèi)核參數(shù)調(diào)優(yōu)實戰(zhàn)指南

    Linux 內(nèi)核參數(shù)調(diào)優(yōu)是系統(tǒng)性能優(yōu)化的核心環(huán)節(jié)。隨著云原生架構(gòu)的普及和硬件性能的飛速提升,默認的內(nèi)核參數(shù)配置往往無法充分發(fā)揮系統(tǒng)潛力。在高并發(fā) Web 服務、大數(shù)據(jù)處理、容器化部署等
    的頭像 發(fā)表于 01-28 14:27 ?659次閱讀

    【「Linux 設備驅(qū)動開發(fā)(第 2 版)」閱讀體驗】+讀深入理解Linux內(nèi)核內(nèi)存分配

    ,目前4KB是廣泛使用的頁大小。在Linux操作系統(tǒng)中,每個進程甚至內(nèi)核本身都被分配了地址空間,這是處理器的虛擬地址空間的一部分,內(nèi)核和進程都不處理
    發(fā)表于 01-16 20:05

    【「Linux 設備驅(qū)動開發(fā)(第 2 版)」閱讀體驗】Linux內(nèi)核開發(fā)基礎

    ,本文介紹Linux內(nèi)核開發(fā)基礎 處理內(nèi)核的核心輔助函數(shù) Linux內(nèi)核加鎖機制和共享資源 無論
    發(fā)表于 01-12 22:45

    請問沒有用到的I/0如何處理

    沒有用到的I/0如何處理?
    發(fā)表于 01-12 06:29

    【「Linux 設備驅(qū)動開發(fā)(第 2 版)」閱讀體驗】+讀內(nèi)核處理的核心輔助函數(shù)

    處理內(nèi)核的核心輔助函數(shù)”進行學習。 第3章又是以5個主題展開討論學習,①、Linux內(nèi)核加鎖機制和共享資源;②、處理
    發(fā)表于 01-10 22:08

    深入Linux內(nèi)核:進程調(diào)度的核心邏輯與實現(xiàn)細節(jié)

    ,背后都離不開內(nèi)核調(diào)度算法的精準操控。今天,我們就從優(yōu)先級、調(diào)度算法、時間片分配到底層實現(xiàn),全方位拆解Linux內(nèi)核進程調(diào)度的核心邏輯。 一、進程調(diào)度的“身份標識”:優(yōu)先級與分類 要理解調(diào)度邏輯,首先得搞懂:進程憑什么“插隊”?
    的頭像 發(fā)表于 12-24 07:05 ?4534次閱讀
    深入<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>:進程調(diào)度的核心邏輯與實現(xiàn)細節(jié)

    Linux內(nèi)核模塊的加載機制

    Linux內(nèi)核模塊通常是.ko文件,也就是Kernel Object的縮寫。這些文件是ELF格式的,但和用戶空間的程序不同,它們包含的是特定于內(nèi)核的信息。比如,模塊的元數(shù)據(jù),像作者、許可證、描述等
    發(fā)表于 11-25 06:59

    deepin亮相2025中國Linux內(nèi)核開發(fā)者大會

    11 月 1 日,第二十屆中國 Linux 內(nèi)核開發(fā)者大會(CLK)在深圳舉辦。CLK 作為國內(nèi) Linux 內(nèi)核領域極具影響力的峰會,由清華大學、Intel、華為、阿里云、富士通南大
    的頭像 發(fā)表于 11-05 17:59 ?915次閱讀

    Linux內(nèi)核參數(shù)調(diào)優(yōu)方案

    在高并發(fā)微服務環(huán)境中,網(wǎng)絡性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細化的Linux內(nèi)核參數(shù)調(diào)優(yōu),讓你的K8s節(jié)點網(wǎng)絡性能提升30%以上。
    的頭像 發(fā)表于 08-06 17:50 ?1136次閱讀

    如何配置和驗證Linux內(nèi)核參數(shù)

    Linux系統(tǒng)運維和性能優(yōu)化中,內(nèi)核參數(shù)(sysctl)的配置至關重要。合理的參數(shù)調(diào)整可以顯著提升網(wǎng)絡性能、系統(tǒng)穩(wěn)定性及資源利用率。然而,僅僅修改參數(shù)是不夠的,如何驗證這些參數(shù)是否生效同樣關鍵。
    的頭像 發(fā)表于 05-29 17:40 ?1331次閱讀
    南宁市| 江城| 明星| 合作市| 鄯善县| 河池市| 青岛市| 中阳县| 呼图壁县| 尉犁县| 普格县| 永州市| 平阳县| 印江| 罗江县| 苏州市| 堆龙德庆县| 榆林市| 翁源县| 台安县| 南雄市| 鹿泉市| 桑植县| 沧源| 尉氏县| 嘉峪关市| 青阳县| 广汉市| 榆树市| 桃江县| 彰化市| 丰县| 正阳县| 合阳县| 宝坻区| 高安市| 织金县| 凉山| 沧州市| 余姚市| 兴国县|