Linux筆記---信號(上)

1. 信號的概念

Linux下的信號機制是一種進程間通信(IPC)的方式,用于在不同進程之間傳遞信息。

信號是一種異步的信息傳遞方式,這意味著發送信號的進程只發送由信號作為載體的命令,而并不關心接收信號的進程如何處置這個命令(做不做、何時做、怎么做、結果如何等)。

這樣,在發送完命令之后,發送命令的進程就可以著手自己的其他任務,而無需等待對方反饋的結果(或者說無需與對方進行同步)。同時也就意味著接收信號的進程對于命令的處置是相對自由的,甚至可以直接忽略。

例如,菜鳥驛站給你發消息告訴你包裹到了(這就是一種信號),你可以去取,也可以不取(富哥不想要了,又懶得退款,或者單純忘了);你可以立即去取,也可以等幾個小時/幾天再取;你可以自己去取,也可以叫好友幫取,甚至叫個跑腿去取。

但有時候我們又希望自己發送的信號是絕對有效的,不可被輕視的。于是,我們可以將信號分為可靠信號和不可靠信號,一共62種(1~64,除開32和33):

  • 不可靠信號:也稱為非實時信號,不支持排隊,信號可能會丟失。比如發送多次相同的信號,進程只能收到一次,信號值取值區間為1~31。

  • 可靠信號:也稱為實時信號,支持排隊,信號不會丟失,發多少次,就可以收到多少次,信號值取值區間為34~64。

使用 [ kill -l ] 指令可以進行查看:?

2. 信號的處理

2.1 默認處理

每個信號都有默認的處理方式,如SIGINT信號的默認處理是終止進程,SIGTERM信號的默認處理也是終止進程,SIGSEGV信號的默認處理是產生核心轉儲并終止進程。

man 7 signal

找到標題:Standard signals

  • Core(核心轉儲并終止進程):如SIGABRT、SIGFPE信號,當這些信號發生時,系統會進行核心轉儲并且終止進程。
  • Term(終止進程):像SIGALRM、SIGHUP信號,這些信號的默認動作是終止進程。
  • Ign(忽略信號):對于SIGCHLD、SIGCLD信號,系統默認會忽略這些信號。
  • Cont(繼續執行):對于SIGCONT信號,其默認動作是如果進程處于停止狀態則繼續執行。
  • Stop(停止進程):對于SIGSTOP信號,它會使進程停止執行,且不能被捕獲、忽略或阻塞。

可以看到,大多數信號的默認處理方式都是終止進程。

2.2 捕獲信號

進程可以通過設置信號處理函數來捕獲信號并執行自定義的處理邏輯。例如,可以在信號處理函數中記錄日志、進行資源清理等操作。

#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

功能

設置信號處理程序signal函數用于設置一個函數來處理特定的信號。當指定的信號發生時,系統會調用相應的信號處理函數。

參數

sig:表示要處理的信號碼。常見的信號常量包括SIGABRT(程序異常終止)、SIGFPE(算術運算出錯)、SIGILL(非法指令)、SIGINT(中斷信號,如Ctrl+C)、SIGSEGV(非法訪問存儲器)、SIGTERM(終止請求)等。

func:是一個指向函數的指針,用于指定信號處理程序。可以是自定義的函數,也可以是以下預定義函數之一:

  • SIG_DFL:表示使用該信號的默認處理程序。

  • SIG_IGN:表示忽略該信號。

返回值

成功時:返回信號處理程序之前的值。

出錯時:返回SIG_ERR

例如,我們編寫一個循環打印 hello world 的程序, 并讓他捕獲2號信號,即ctrl + c發出的信號:

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void SigHandler(int sigid)
{std::cout << "獲得信號: " << sigid << std::endl;exit(sigid);
}int main()
{signal(SIGINT, SigHandler);for(int i = 0; true; i++){std::cout << "Hello World[" << i << "]" << ", pid:["  << getpid() << "]" << std::endl;sleep(1);}return 0;
}

當我們在程序運行的過程中按下 ctrl + c 時,程序會顯示獲得信號:

2.3?忽略信號

進程可以通過設置信號處理函數為SIG_IGN來忽略某個信號。但有些信號是不能被忽略的,如SIGKILLSIGSTOP信號。

3. 信號的產生方式

  • 用戶輸入:用戶在終端輸入特定的快捷鍵組合,如Ctrl+C會產生SIGINT信號,Ctrl+\會產生SIGQUIT信號,Ctrl+Z會產生SIGTSTP信號。

  • 程序執行異常:當程序執行過程中出現錯誤或異常情況時,內核會發送相應的信號。例如,對一個數除0會產生SIGFPE信號,非法訪問一段內存會產生SIGBUS信號,訪問未分配的虛擬內存會產生SIGSEGV信號。

  • 進程間發送信號:一個進程可以通過系統調用向另一個進程發送信號。例如,使用kill函數可以向指定進程發送信號,raise函數可以向本進程發送信號,sigqueue函數可以向一個進程發送信號并傳遞額外數據。

用戶輸入方式我們在前面已經見識過,就不再多說。

3.1?程序執行異常

我們的程序在遇到運行時錯誤時會報錯并退出,這就是因為程序在發生執行異常時會引發硬件異常中斷,操作系統檢測到之后,就會向引發異常的進程發送一個信號,進而終止進程。

下面的代碼中,我們嘗試捕捉由除零引發的異常和使用野指針引發的異常:

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void SigHandler(int sigid)
{std::cout << "獲得信號: " << sigid << std::endl;exit(sigid);
}int main()
{for(int i = 1; i < 32; i++){signal(i, SigHandler);}// 8) SIGFPEint a = 10;a /= 0;// 11) SIGSEGV// int *p = nullptr;// *p = 100;return 0;
}

除零異常導致程序退出:

使用野指針導致程序退出:

3.2 進程間發送信號

3.2.1 kill命令
kill -[信號編號] [指定進程pid]

?在命令行使用kill指令可像指定進程發送指定信號。

3.2.2 kill函數
#include <sys/types.h>
#include <signal.h>int kill(pid_t pid, int sig);

功能

kill函數用于向指定的進程或進程組發送信號,以實現進程間的通知或控制。

參數

  • pid:表示要發送信號的目標進程或進程組的標識符。

    • pid > 0:將信號發送給進程標識為pid的進程。

    • pid = 0:將信號發送給與調用kill函數的進程屬于同一進程組的所有進程。

    • pid = -1:將信號發送給除了進程1(init進程)和調用者自身以外的所有進程。

    • pid < -1:將信號發送給進程組ID等于pid絕對值的所有進程。

  • sig:表示要發送的信號。可以是以下常見信號常量之一

返回值

  • 成功時:返回0。

  • 出錯時:返回-1,并設置errno以指示錯誤原因。

?3.2.3 raise函數
#include <signal.h>int raise(int sig);
  • 功能:向調用該函數的進程發送一個信號(即向自己發送信號)。

  • 參數sig表示要發送的信號編號。

  • 返回值:成功時返回0;失敗時返回非0值。

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void SigHandler(int sigid)
{std::cout << "獲得信號: " << sigid << std::endl;exit(sigid);
}int main()
{for(int i = 1; i < 32; i++){signal(i, SigHandler);}for(int i = 1; i < 32; i++){sleep(1);// 給自己發信號if(i == 9 || i == 19) // 9-SIGKILL 19-SIGSTOP不能被自定義捕獲 continue;raise(i);}return 0;
}

?9號信號SIGKILL和19號信號SIGSTOP無法被自定義捕獲,這是為了防止出現所有信號都被捕獲而無法通過信號使目標進程被強制停止的情況。

3.2.4 abort函數
#include <stdlib.h>void abort(void);

功能abort函數用于立即終止當前程序的執行,通常在檢測到不可恢復的錯誤時使用。

特點

  • 不執行清理工作abort函數不會執行任何atexit注冊的函數或對象析構函數,也不會刷新流緩沖區或關閉打開的文件等常規清理操作。

  • 產生核心轉儲文件:在某些系統上,如果系統配置允許,abort函數會產生一個核心轉儲文件,用于調試程序異常終止的原因。

  • 發送信號abort函數會向調用進程發送SIGABRT信號,進程不應忽略此信號。

3.2.5 sigqueue函數

功能:向指定的進程發送特定的信號,并可以傳遞一個額外的數據值,提供了比kill函數更豐富的功能,可用于進程間的高級通信。

暫時不做介紹。

4. 補充:前后臺進程

在大多數用戶交互式操作系統當中,都會把進程分為前臺進程和后臺進程,在Linux中二者的概念如下:

  • 前臺進程:是與用戶直接交互的進程,占有控制終端,可以從終端接收輸入并向終端發送輸出。在任何時刻,只有一個進程組可以在前臺運行。

  • 后臺進程:是不與用戶直接交互的進程,在后臺默默運行,不占用控制終端。

用戶在命令行啟動可執行程序時,該可執行程序默認以前臺方式運行,由于前臺進程只有一個,所以操作系統會將bash切換到后臺運行,待可執行程序運行結束或者被切換到后臺時,再將bash切換回前臺。

如果用戶希望進程被啟動后在后臺運行,可在其后跟上 & :

可以看到,我們讓SigTest運行起來之后,bash和SigTest都在往標準輸出打印,當我們輸入ls指令之后,發現處于前臺的bash獲得了我們的輸入,并運行了ls。

此時,如果我們想要通過[ctrl + c]的方式來結束SigTest是行不通的,因為只有前臺進程能接收到我們的輸入。此時我們有兩種做法:

  • 使用kill -9指定終止SigTest。
  • 將SigTest放到前臺,再使用[ctrl + c]。

前者不再進行說明了,接下來我們講解一下如何在命令行控制進程的前后臺切換。

在Linux中,與前后臺相關的指令主要用于管理進程的運行狀態,以下是一些常用的指令:

后臺運行指令

  • &:在命令末尾添加“&”符號,可以使程序在后臺運行,例如“./matmul &”將運行一個名為matmul的程序并使其在后臺運行,這樣用戶就可以在前臺繼續執行其他命令。
  • nohup:nohup命令用于在后臺運行命令,即使終端關閉或用戶退出,命令也會繼續執行。例如,“nohup ping 101.lug.ustc.edu.cn &”將在后臺運行ping命令,并將輸出重定向到nohup.out文件中。

前后臺切換指令

  • Ctrl+Z:將當前正在前臺執行的命令或進程暫停,并放入后臺。例如,當一個命令在前臺運行時,按下Ctrl+Z,該命令將被暫停并放入后臺,屏幕上會顯示相關的狀態信息。
  • jobs:用于查看當前在后臺運行的進程或任務的列表,以及它們的狀態和作業號。例如,“jobs -l”將顯示詳細的后臺進程信息,包括進程ID、狀態等。
  • fg:將后臺中的進程調至前臺繼續運行。例如,“fg %1”將把后臺中作業號為1的進程調至前臺運行。
  • bg:將后臺中暫停的進程繼續在后臺運行。例如,“bg %2”將使后臺中作業號為2的進程在后臺繼續運行。

其他相關指令

  • ps:用于查看當前系統中正在運行的進程的狀態和信息。例如,“ps aux”將顯示所有用戶的所有進程的詳細信息。
  • kill:用于向進程發送信號,通常用于終止進程。例如,“kill -9 PID”將強制終止指定PID的進程。
  • top:用于實時查看系統中各個進程的資源占用情況,包括CPU、內存等。
  • htop:是top命令的增強版,提供了更直觀和交互性更強的界面,用于查看和管理進程。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80687.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80687.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80687.shtml

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

相關文章

UG 二次開發- UG內部調用DLL

【1】用VS新建一個dll工程 將項目設置為x64平臺&#xff08;這步很重要&#xff0c;否則程序無法編譯成功&#xff09; 【2】添加UG頭文件目錄&#xff0c;屬性頁->C/C->常規->附加包含目錄 【3】添加UG庫所在目錄&#xff0c;屬性頁->鏈接器->常規->附加庫目…

wordcount在mapreduce的例子

1.啟動集群 2.創建項目 項目結構為&#xff1a; 3.pom.xml文件為 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://mave…

智慧城市綜合運營管理系統Axure原型

這款Axure原型的設計理念緊緊圍繞城市管理者的需求展開。它旨在打破傳統城市管理中信息孤島的局面&#xff0c;通過統一標準接入各類業務系統&#xff0c;實現城市運營管理信息資源的全面整合與共享。以城市管理者為中心&#xff0c;為其提供一個直觀、便捷、高效的協同服務平臺…

Go語言:json 作用和語法

在 Go 語言中&#xff0c;JSON 字段&#xff08;也稱為 JSON Tag&#xff09;是附加在結構體字段上的元數據&#xff0c;用于控制該字段在 JSON 編碼&#xff08;序列化&#xff09;和解碼&#xff08;反序列化&#xff09; 時的行為。它的語法是&#xff1a; type StructName…

MATLAB復制Excel數據到指定區域

Matlab中如何將Excel表中的265-528行F-AA列數據復制到1-263行AE-AZ中 版本&#xff1a;MatlabR2018b clc; clear; %舊Excel文件名 oldFile ; %新Excel文件名 newFile ; % 工作表名稱&#xff08;舊表和新表一致&#xff09; sheetName Sheet1; % 舊文件中待復制的數據范…

vue3+flask+sqlite前后端項目實戰

基礎環境安裝 pycharm 下載地址&#xff1a; https://www.jetbrains.com/zh-cn/pycharm/download/?sectionwindows vscode 下載地址 https://code.visualstudio.com/docs/?dvwin64user python 下載地址 https://www.python.org/downloads/windows/ Node.js&#xff08;含npm…

Java 內存模型(JMM)與內存屏障:原理、實踐與性能權衡

Java 內存模型&#xff08;JMM&#xff09;與內存屏障&#xff1a;原理、實踐與性能權衡 在多線程高并發時代&#xff0c;Java 內存模型&#xff08;JMM&#xff09; 及其背后的內存屏障機制&#xff0c;是保障并發程序正確性與性能的基石。本文將系統梳理 JMM 的核心原理、內…

動手學深度學習12.3.自動并行-筆記練習(PyTorch)

以下內容為結合李沐老師的課程和教材補充的學習筆記&#xff0c;以及對課后練習的一些思考&#xff0c;自留回顧&#xff0c;也供同學之人交流參考。 本節課程地址&#xff1a;無 本節教材地址&#xff1a;12.3. 自動并行 — 動手學深度學習 2.0.0 documentation 本節開源代…

C++類和對象之初始化列表

初始化列表 C初始化列表詳解&#xff1a;性能優化與正確實踐什么是初始化列表&#xff1f;初始化列表的三大核心作用1. 性能優化&#xff1a;避免不必要的賦值操作2. 強制初始化&#xff1a;處理const和引用成員3. 基類初始化&#xff1a;正確調用父類構造函數4.必須使用初始化…

continue通過我們的開源 IDE 擴展和模型、規則、提示、文檔和其他構建塊中心,創建、共享和使用自定義 AI 代碼助手

?一、軟件介紹 文末提供程序和源碼下載 Continue 使開發人員能夠通過我們的開源 VS Code 和 JetBrains 擴展以及模型、規則、提示、文檔和其他構建塊的中心創建、共享和使用自定義 AI 代碼助手。 二、功能 Chat 聊天 Chat makes it easy to ask for help from an LLM without…

基于Spring Boot + Vue的母嬰商城系統( 前后端分離)

一、項目背景介紹 隨著母嬰行業在互聯網平臺的快速發展&#xff0c;越來越多的家庭傾向于在線選購母嬰產品。為了提高商品管理效率和用戶購物體驗&#xff0c;本項目開發了一個基于 Spring Boot Vue 技術棧的母嬰商城系統&#xff0c;實現了商品分類、商品瀏覽、資訊展示、評…

實戰演練:用 AWS Lambda 和 API Gateway 構建你的第一個 Serverless API

實戰演練:用 AWS Lambda 和 API Gateway 構建你的第一個 Serverless API 理論千遍,不如動手一遍!在前面幾篇文章中,我們了解了 Serverless 的概念、FaaS 的核心原理以及 BaaS 的重要作用。現在,是時候把這些知識運用起來,親手構建一個簡單但完整的 Serverless 應用了。 …

node.js 實戰——express圖片保存到本地或服務器(七牛云、騰訊云、阿里云)

本地 ? 使用formidable 讀取表單內容 npm i formidable ? 使用mime-types 獲取圖片后綴 npm install mime-types? js 中提交form表單 document.getElementById(uploadForm).addEventListener(submit, function(e){e.preventDefault();const blob preview._blob;if(!blob)…

2025最新:3分鐘使用Docker快速部署單節點Redis

&#x1f9d1;?&#x1f3eb; 詳細教程&#xff1a;通過 Docker 安裝單節點 Redis &#x1f6e0;? 前提條件&#xff1a; 你需要在 Ubuntu 系統上進行操作&#xff08;如果你在其他系統上操作&#xff0c;可以按相似步驟進行調整&#xff09;。已安裝 Docker 和 Docker Com…

CentOS 7 系統下安裝 OpenSSL 1.0.2k 依賴問題的處理

前面有提到過這個openssl的版本沖突問題&#xff0c;也是在這次恢復服務器時遇到的問題&#xff0c;我整理如下&#xff0c;供大家參考。小小一個軟件的安裝&#xff0c;挺坑的。 一、問題 項目運行環境需要&#xff0c;指定PHP7.0.9這個版本&#xff0c;但是?系統版本與軟件…

LoRA(Low-Rank Adaptation)原理詳解

LoRA(Low-Rank Adaptation)原理詳解 LoRA(低秩適應)是一種參數高效微調(Parameter-Efficient Fine-Tuning, PEFT)技術,旨在以極低的參數量實現大模型在特定任務上的高效適配。其核心思想基于低秩分解假設,即模型在適應新任務時,參數更新矩陣具有低秩特性,可用少量參…

Solana批量轉賬教程:提高代幣持有地址和生態用戶空投代幣

前言 Solana區塊鏈因其高吞吐量和低交易費用成為批量操作&#xff08;如空投&#xff09;的理想選擇。本教程將介紹幾種在Solana上進行批量轉賬的方法&#xff0c;幫助您高效地向多個地址空投代幣。 solana 賬戶模型 在Solana中有三類賬戶&#xff1a; 數據賬戶&#xff0c;…

基于LSTM與SHAP可解釋性分析的神經網絡回歸預測模型【MATLAB】

基于LSTM與SHAP可解釋性分析的神經網絡回歸預測模型【MATLAB】 一、引言 在數據驅動的智能時代&#xff0c;時間序列預測已成為許多領域&#xff08;如金融、氣象、工業監測等&#xff09;中的關鍵任務。長短期記憶網絡&#xff08;LSTM&#xff09;因其在捕捉時間序列長期依…

手機網頁提示ip被拉黑名單什么意思?怎么辦

?當您使用手機瀏覽網頁時&#xff0c;突然看到“您的IP地址已被列入黑名單”的提示&#xff0c;是否感到困惑和不安&#xff1f;這種情況在現代網絡生活中并不罕見&#xff0c;但確實會給用戶帶來諸多不便。本文將詳細解釋IP被拉黑的含義、常見原因&#xff0c;并提供一系列實…

Java消息隊列性能優化實踐:從理論到實戰

Java消息隊列性能優化實踐&#xff1a;從理論到實戰 1. 引言 在現代分布式系統架構中&#xff0c;消息隊列&#xff08;Message Queue&#xff0c;MQ&#xff09;已經成為不可或缺的中間件組件。它不僅能夠實現系統間的解耦&#xff0c;還能提供異步通信、流量削峰等重要功能…