博客專欄

        EEPW首頁 > 博客 > 嵌入式Linux:信號是什么?

        嵌入式Linux:信號是什么?

        發布人:美男子玩編程 時間:2024-09-25 來源:工程師 發布文章

        信號是Linux系統中用于通知進程事件發生的一種機制,可以將其視為一種軟件中斷。


        信號類似于硬件中斷,能夠打斷進程當前的執行流程,從而實現對中斷機制的一種軟件層面的模擬。信號的主要作用是處理異步事件,因為大多數情況下,信號的到達時間是不可預測的。


        信號的一個主要目的是用于進程間的通信。具有合適權限的進程可以向另一個進程發送信號,這種用法不僅可以用作一種同步技術,還可以視為進程間通信(IPC)的最基礎形式。


        1

        信號的來源

        信號可以由多種情況觸發,以下是常見的幾種信號來源:


        硬件異常

        硬件檢測到錯誤條件并通知內核,內核隨即發送相應的信號給相關進程。例如,當執行除數為零、訪問越界的內存等異常操作時,硬件會捕捉到這些錯誤并通知內核,內核則向相關進程發送信號,如SIGFPE(浮點異常)或SIGSEGV(非法內存訪問)。


        終端輸入特殊字符

        用戶通過終端輸入特定的控制字符可以產生信號。例如,按下CTRL + C組合鍵會產生SIGINT(中斷信號),可以終止前臺運行的進程;按下CTRL + Z會產生SIGTSTP(暫停信號),可暫停當前前臺運行的進程。


        進程調用系統調用

        進程可以通過kill()系統調用向另一個進程或進程組發送信號。為了確保系統安全,發送信號的進程和接收信號的進程通常需要具有相同的所有者,或者發送信號的進程的所有者是root超級用戶。


        用戶命令

        用戶可以通過kill命令向其它進程發送信號。雖然kill命令的名稱聽起來像是用來“殺死”進程,但實際上它可以發送任意信號。例如,kill -9 PID會向進程發送SIGKILL信號,強制終止指定進程。


        軟件事件

        軟件檢測到特定條件發生時也會產生信號。這些條件可能包括:進程設置的定時器到期、進程使用的CPU時間超限、子進程退出等。這些信號通常由內核觸發并發送給相關進程。


        2

        信號的處理方式

        當信號到達進程時,進程需要對該信號進行處理。通常,進程對信號的處理方式有以下幾種:


        忽略信號

        進程可以選擇忽略某些信號,使其不對進程的執行產生影響。然而,有兩種信號SIGKILL和SIGSTOP是無法被忽略的,因為它們提供了終止或停止進程的可靠方法。如果進程忽略某些由硬件異常產生的信號,其行為可能是未定義的。


        捕獲信號

        進程可以捕獲并處理信號,通過預先定義的信號處理函數來響應特定的信號。為了實現這一點,進程需要通過signal()或sigaction()系統調用來注冊信號處理函數,當信號發生時,該函數將被執行以處理相應的事件。


        執行系統默認操作

        如果進程沒有捕獲信號,系統會對信號進行默認處理。對于大多數信號,系統默認的處理方式是終止進程。然而,也有些信號的默認處理方式是忽略。


        3

        信號的異步性

        信號是異步事件的經典實例。信號的產生對進程而言是隨機的,進程無法預測信號到達的具體時間。這種異步性與硬件中斷非常相似。進程無法通過簡單的變量測試或系統調用判斷信號是否產生,只有當信號實際發生時,系統才會通知進程,打斷當前執行流程,跳轉到信號處理函數去執行相應操作。


        4

        信號編號

        在Linux系統中,信號本質上是int類型的數字編號,類似于硬件中斷所對應的中斷號。內核為每一個信號定義了一個唯一的整數編號,這些編號從數字1開始依次展開。每個信號都有一個對應的名字,這個名字實際上是一個宏,通常以SIGxxx的形式出現,例如SIGINT、SIGKILL等。


        信號的整數編號與其符號名之間是一一對應的關系,但由于不同操作系統的實現可能存在差異,某些信號的實際編號在不同系統中可能會有所不同。為了提高程序的可移植性,在編寫代碼時,開發者通常使用信號的符號名而不是直接使用編號。例如,在程序中使用SIGINT來表示中斷信號,而不是直接使用數字2(在大多數系統中,SIGINT的編號為2)。


        信號的定義可以在或頭文件中找到,這些文件中定義了所有標準信號的編號和名稱。


        需要注意,信號編號從1開始,而編號為0的信號在標準定義中并不存在。


        #define SIGHUP      1  /* 掛斷 (POSIX). */#define SIGINT      2  /* 中斷 (ANSI). */#define SIGQUIT     3  /* 退出 (POSIX). */#define SIGILL      4  /* 非法指令 (ANSI). */#define SIGTRAP     5  /* 跟蹤陷阱 (POSIX). */#define SIGABRT     6  /* 異常終止 (ANSI). */#define SIGIOT      6  /* IOT 陷阱 (4.2 BSD). */#define SIGBUS      7  /* 總線錯誤 (4.2 BSD). */#define SIGFPE      8  /* 浮點異常 (ANSI). */#define SIGKILL     9  /* 終止,無法阻塞 (POSIX). */#define SIGUSR1    10  /* 用戶自定義信號 1 (POSIX). */#define SIGSEGV    11  /* 段錯誤 (ANSI). */#define SIGUSR2    12  /* 用戶自定義信號 2 (POSIX). */#define SIGPIPE    13  /* 管道破裂 (POSIX). */#define SIGALRM    14  /* 鬧鐘信號 (POSIX). */#define SIGTERM    15  /* 終止 (ANSI). */#define SIGSTKFLT  16  /* 棧錯誤. */#define SIGCHLD    17  /* 子進程狀態改變 (POSIX). */#define SIGCLD     SIGCHLD /* 與 SIGCHLD 相同 (System V). */#define SIGCONT    18  /* 繼續執行 (POSIX). */#define SIGSTOP    19  /* 停止,無法阻塞 (POSIX). */#define SIGTSTP    20  /* 終端停止信號 (POSIX). */#define SIGTTIN    21  /* 后臺從終端讀取 (POSIX). */#define SIGTTOU    22  /* 后臺向終端寫入 (POSIX). */#define SIGURG     23  /* 套接字緊急情況 (4.2 BSD). */#define SIGXCPU    24  /* 超過 CPU 時間限制 (4.2 BSD). */#define SIGXFSZ    25  /* 超過文件大小限制 (4.2 BSD). */#define SIGVTALRM  26  /* 虛擬時鐘信號 (4.2 BSD). */#define SIGPROF    27  /* 程序執行時鐘信號 (4.2 BSD). */#define SIGWINCH   28  /* 窗口大小改變 (4.3 BSD, Sun). */#define SIGPOLL    SIGIO  /* 可輪詢事件發生 (System V). */#define SIGIO      29  /* I/O 操作完成 (4.2 BSD). */#define SIGPWR     30  /* 電源故障重啟 (System V). */#define SIGSYS     31  /* 錯誤的系統調用. */#define SIGUNUSED  31  /* 未使用的信號. */


        在 Linux 系統下使用"kill -l"命令可查看到所有信號,如下所示:



        在實際開發中,合理使用信號處理機制可以提高程序的健壯性和響應速度。開發者需要根據應用場景選擇合適的信號處理方式,比如在關鍵任務中確保某些信號能夠及時處理,或者在某些情況下忽略不重要的信號以避免不必要的中斷。

        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: 嵌入式 Linux

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 常山县| 乌鲁木齐县| 全州县| 元氏县| 尼勒克县| 林州市| 称多县| 正定县| 苏尼特右旗| 峨眉山市| 彭山县| 灵宝市| 新田县| 井冈山市| 苏尼特右旗| 辽阳市| 息烽县| 大石桥市| 阿克苏市| 江津市| 同江市| 都江堰市| 禹州市| 任丘市| 鄱阳县| 康马县| 宿松县| 蓬溪县| 天津市| 岳阳县| 榆中县| 宁河县| 朔州市| 漳平市| 滕州市| 临沂市| 石门县| 义马市| 南丰县| 临江市| 甘孜|