【Linux】24.進程信號(1)

文章目錄

  • 1. 信號入門
    • 1.1 進程與信號的相關知識
    • 1.2 技術應用角度的信號
    • 1.3 注意
    • 1.4 信號概念
    • 1.5 信號處理常見方式概覽
  • 2. 產生信號
    • 2.1 通過終端按鍵產生信號
    • 2.2 調用系統函數向進程發信號
    • 2.3 由軟件條件產生信號
    • 2.4 硬件異常產生信號
    • 2.5 信號保存
  • 3. 阻塞信號
    • 3.1 信號其他相關常見概念
    • 3.2 在內核中的表示
    • 3.3 sigset_t
    • 3.4 信號集操作函數
      • sigprocmask
      • sigpending


1. 信號入門

1.1 進程與信號的相關知識

  1. 進程 必須 識別+能夠處理信號(信號沒有產生,也要具備處理信號的能力)信號的處理能力,屬于進程內置功能的一部分

  2. 進程即便是沒有收到信號,也能知道哪些信號該怎么處理

  3. 當進程真的收到了一個具體的信號的時候,進程可能并不會立即處理這個信號,需要等到合適的時候

  4. 一個進程,當信號產生到信號開始被處理,就一定會有時間窗口,進程具有臨時保存哪些信號已經發生了的能力


1.2 技術應用角度的信號

用戶輸入命令,在Shell下啟動一個前臺進程。

用戶按下Ctrl+C ,這個鍵盤輸入產生一個硬件中斷,被OS獲取,解釋成信號,發送給目標前臺進程

前臺進程因為收到信號,進而引起進程退出

ctrl+c為什么能夠殺掉我們前臺進程呢?

Linux中,一次登陸中,一個終端一般會配上一個bash,每一個登陸,只允許一個進程是前臺進程,可以允許多個進程是后臺進程。

鍵盤輸入首先是被前臺進程收到的。(這是前臺進程和后臺進程的本質區別)

ctrl +c本質是被進程解釋成為收到了信號。ctrl+c 會觸發SIGINT信號(信號編號2),然后終端驅動程序捕獲這個按鍵組合,將SIGINT信號發送給前臺進程組的所有進程。

  1. 前臺進程特性

    • 與終端關聯

    • 能夠接收終端輸入

    • 屬于當前終端的前臺進程組

  2. 只能終止前臺進程的原因

    • 終端只與前臺進程組關聯

    • 后臺進程組收不到終端產生的信號

關鍵點:ctrl+c 本質是通過信號機制來終止進程的,而不是直接"殺死"進程。

b1cca7f77b86b1a13f67caf132fd63bf

1-31是普通信號,34-64是實時信號。

信號的處理方式:

  1. 默認動作

  2. 忽略

  3. 自定義動作(信號的捕捉)

例如紅燈亮了就等綠燈是默認動作,不管紅燈闖紅燈就是忽略,紅燈了唱歌跳舞就是自定義動作。

進程收到2號信號的默認動作,就是終止自己。

不是所有的信號都是可以被signal捕捉的,比如:9,19。

但是無論信號如何產生,最終一定是誰發送給進程的?

OS,因為OS是進程的管理者。


1.3 注意

  1. Ctrl+C 產生的信號只能發給前臺進程。一個命令后面加個&可以放到后臺運行,這樣Shell不必等待進程結束就可以接受新的命令,啟動新的進程。
  2. Shell可以同時運行一個前臺進程和任意多個后臺進程,只有前臺進程才能接到像 Ctrl+C 這種控制鍵產生的信號。
  3. 前臺進程在運行過程中用戶隨時可能按下 Ctrl+C 而產生一個信號,也就是說該進程的用戶空間代碼執行到任何地方都有可能收到 SIGINT 信號而終止,所以信號相對于進程的控制流程來說是異步(Asynchronous)的。

1.4 信號概念

信號是進程之間事件異步通知的一種方式,屬于軟中斷。


1.5 信號處理常見方式概覽

(sigaction函數稍后詳細介紹),可選的處理動作有以下三種:

  1. 忽略此信號。
  2. 執行該信號的默認處理動作。
  3. 提供一個信號處理函數,要求內核在處理該信號時切換到用戶態執行這個處理函數,這種方式稱為捕捉(Catch)一個信號。

2. 產生信號

2.1 通過終端按鍵產生信號

SIGINT的默認處理動作是終止進程,SIGQUIT的默認處理動作是終止進程并且Core Dump。

Core Dump

首先解釋什么是Core Dump。當一個進程要異常終止時,可以選擇把進程的用戶空間內存數據全部 保存到磁盤上,文件名通常是core,這叫做Core Dump。

進程異常終止通常是因為有Bug,比如非法內存訪問導致段錯誤,事后可以用調試器檢查core文件以查清錯誤原因,這叫做Post-mortem Debug(事后調試)。一個進程允許產生多大的core文件取決于進程的Resource Limit(這個信息保存 在PCB中)。

默認是不允許產生core文件的,因為core文件中可能包含用戶密碼等敏感信息,不安全。在開發調試階段可以用ulimit命令改變這個限制,允許產生core文件。


2.2 調用系統函數向進程發信號

首先在后臺執行死循環程序,然后用kill命令給它發SIGSEGV信號。

kill命令是調用kill函數實現的。kill函數可以給一個指定的進程發送指定的信號。

raise函數可以給當前進程發送指定的信號(自己給自己發信號)。

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
這兩個函數都是成功返回0,錯誤返回-1

abort函數使當前進程接收到信號而異常終止。

#include <stdlib.h>
void abort(void);
就像exit函數一樣,abort函數總是會成功的,所以沒有返回值。

2.3 由軟件條件產生信號

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
調用alarm函數可以設定一個鬧鐘,也就是告訴內核在seconds秒之后給當前進程發SIGALRM信號, 該信號的默認處理動作是終止當前進程。

2.4 硬件異常產生信號

硬件異常被硬件以某種方式被硬件檢測到并通知內核,然后內核向當前進程發送適當的信號。以下是幾種常見的硬件異常及其對應的信號:

  1. 除零異常(SIGFPE):
    當程序執行除以0的操作時,CPU的算術邏輯單元會檢測到這個異常。例如:
int a = 1;
int b = 0;
int c = a / b;  // 觸發SIGFPE信號
  1. 段錯誤(SIGSEGV):
    當程序訪問了非法內存地址時,內存管理單元(MMU)會產生異常。例如:
int *p = NULL;
*p = 1;         // 訪問空指針,觸發SIGSEGV信號int arr[10];
arr[10000] = 1; // 數組越界,可能觸發SIGSEGV信號
  1. 非法指令(SIGILL):
    當CPU執行了非法指令時產生此信號:
void (*bad_func_ptr)() = (void (*)())0x12345678;
bad_func_ptr();  // 執行非法地址的代碼,觸發SIGILL信號
  1. 總線錯誤(SIGBUS):
    當訪問未對齊的內存地址時可能產生此信號:
char *ptr = (char *)0x12345;
int *iptr = (int *)ptr;
*iptr = 1;      // 可能觸發SIGBUS信號

在系統層面,這些硬件異常的處理流程是:

  1. 硬件檢測到異常
  2. 觸發CPU中斷
  3. CPU切換到內核態
  4. 內核將硬件異常轉換為相應的信號
  5. 內核向進程發送信號
  6. 如果進程注冊了信號處理函數,則執行該函數
  7. 如果沒有注冊處理函數,則執行信號的默認處理動作(通常是終止進程)

這就是為什么C/C++中的很多運行時錯誤(如除零、空指針解引用、數組越界等)最終都表現為進程收到信號并終止。這種機制讓操作系統能夠及時發現并處理程序中的嚴重錯誤,防止錯誤程序繼續運行可能造成的更大危害。


2.5 信號保存

為什么要信號保存?

進程收到信號之后,可能不會立即處理這個信號。信號不會被處理,就要有一個時間窗口。


3. 阻塞信號

3.1 信號其他相關常見概念

  • 實際執行信號的處理動作稱為信號遞達(Delivery)

  • 信號從產生到遞達之間的狀態,稱為信號未決(Pending)。

  • 進程可以選擇阻塞 (Block )某個信號。

  • 被阻塞的信號產生時將保持在未決狀態,直到進程解除對此信號的阻塞,才執行遞達的動作.

  • 注意,阻塞和忽略是不同的,只要信號被阻塞就不會遞達,而忽略是在遞達之后可選的一種處理動作。


3.2 在內核中的表示

信號在內核中的表示示意圖

fca6ee5b6f978ae7d0db9dec37b27c60

  • 每個信號都有兩個標志位分別表示阻塞(block)和未決(pending),還有一個函數指針表示處理動作。信號產生時,內核在進程控制塊中設置該信號的未決標志,直到信號遞達才清除該標志。在上圖的例子中,SIGHUP信號未阻塞也未產生過,當它遞達時執行默認處理動作。

  • SIGINT信號產生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒有解除阻塞之前不能忽略這個信號,因為進程仍有機會改變處理動作之后再解除阻塞。

  • SIGQUIT信號未產生過,一旦產生SIGQUIT信號將被阻塞,它的處理動作是用戶自定義函數sighandler。 如果在進程解除對某信號的阻塞之前這種信號產生過多次,將如何處理?POSIX.1允許系統遞送該信號一次或多次。Linux是這樣實現的:常規信號在遞達之前產生多次只計一次,而實時信號在遞達之前產生多次可以依次放在一個隊列里。本章不討論實時信號。


3.3 sigset_t

從上圖來看,每個信號只有一個bit的未決標志,非0即1,不記錄該信號產生了多少次,阻塞標志也是這樣表示的。

因此,未決和阻塞標志可以用相同的數據類型sigset_t來存儲,sigset_t稱為信號集,這個類型可以表示每個信號的“有效”或“無效”狀態,在阻塞信號集中“有效”和“無效”的含義是該信號是否被阻塞,而在未決信號集中“有效”和“無效”的含義是該信號是否處于未決狀態。下一節將詳細介紹信號集的各種操作。 阻塞信號集也叫做當前進程的信號屏蔽字(Signal Mask),這里的“屏蔽”應該理解為阻塞而不是忽略。


3.4 信號集操作函數

sigset_t類型對于每種信號用一個bit表示“有效”或“無效”狀態,至于這個類型內部如何存儲這些bit則依賴于系統實現,從使用者的角度是不必關心的,使用者只能調用以下函數來操作sigset_ t變量,而不應該對它的內部數據做任何解釋,比如用printf直接打印sigset_t變量是沒有意義的

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo); 
  • 函數sigemptyset初始化set所指向的信號集,使其中所有信號的對應bit清零,表示該信號集不包含 任何有效信號。

  • 函數sigfillset初始化set所指向的信號集,使其中所有信號的對應bit置位,表示 該信號集的有效信號包括系統支持的所有信號。

  • 注意:在使用sigset_ t類型的變量之前,一定要調 用sigemptyset或sigfillset做初始化,使信號集處于確定的狀態。初始化sigset_t變量之后就可以在調用sigaddset和sigdelset在該信號集中添加或刪除某種有效信號。

這四個函數都是成功返回0,出錯返回-1。sigismember是一個布爾函數,用于判斷一個信號集的有效信號中是否包含某種 信號,若包含則返回1,不包含則返回0,出錯返回-1。

sigprocmask

調用函數sigprocmask可以讀取或更改進程的信號屏蔽字(阻塞信號集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 
返回值:若成功則為0,若出錯則為-1

如果oset是非空指針,則讀取進程的當前信號屏蔽字通過oset參數傳出。如果set是非空指針,則 更改進程的信號屏蔽字,參數how指示如何更改。如果oset和set都是非空指針,則先將原來的信號 屏蔽字備份到oset里,然后根據set和how參數更改信號屏蔽字。假設當前的信號屏蔽字為mask,下表說明了how參數的可選值。

b5469757cf1306db6a8ca96d07d949ea

如果調用sigprocmask解除了對當前若干個未決信號的阻塞,則在sigprocmask返回前,至少將其中一個信號遞達。


sigpending

#include <signal.h>
sigpending
讀取當前進程的未決信號集,通過set參數傳出。調用成功則返回0,出錯則返回-1

代碼:

void printsigset(sigset_t *set)
{// 打印信號集中的信號狀態,用1表示信號在集合中,0表示不在for(int i=1; i<32; i++) {if (sigismember(set, i)) {  // 判斷信號i是否在信號集set中putchar('1');} else {putchar('0');}}puts("");
}int main()
{sigset_t s, p;sigemptyset(&s);        // 初始化信號集s為空集sigaddset(&s, SIGINT);  // 將SIGINT信號添加到信號集s中,Ctrl+Csigprocmask(SIG_BLOCK, &s, NULL);  // 設置信號屏蔽字,阻塞SIGINT信號while(1) {sigpending(&p);     // 獲取未決信號集printsigset(&p);    // 打印未決信號集sleep(1);}return 0;
}

程序運行時,每秒鐘把各信號的未決狀態打印一遍,由于我們阻塞了SIGINT信號,按Ctrl+C將會使SIGINT信號處于未決狀態。按Ctrl+\仍然可以終止程序,因為SIGQUIT信號沒有阻塞。

代碼:

// 打印未決信號集的函數
void PrintPending(sigset_t &pending)
{// 從31號信號到1號信號逐個檢查for (int signo = 31; signo >= 1; signo--){if (sigismember(&pending, signo))cout << "1";  // 信號處于未決狀態elsecout << "0";  // 信號不在未決集中}cout << "\n\n";
}// 信號處理函數
void handler(int signo)
{cout << "catch a signo: " << signo << endl;
}int main()
{// 4. 屏蔽所有可屏蔽信號sigset_t bset, oset;sigemptyset(&bset);    // 清空信號集sigemptyset(&oset);    // 清空舊信號集for (int i = 1; i <= 31; i++){sigaddset(&bset, i); // 將所有信號添加到屏蔽集}sigprocmask(SIG_SETMASK, &bset, &oset); // 設置信號屏蔽字// 循環檢測未決信號sigset_t pending;while (true){int n = sigpending(&pending);  // 獲取未決信號集if (n < 0)continue;PrintPending(pending);         // 打印未決信號集sleep(1);}// // 0. 對2號信號進行自定義捕捉// signal(2, handler);// // 1. 先對2號信號進行屏蔽 --- 數據預備// sigset_t bset, oset; // 在哪里開辟的空間???用戶棧上的,屬于用戶區// sigemptyset(&bset);// sigemptyset(&oset);// sigaddset(&bset, 2); // 我們已經把2好信號屏蔽了嗎?并沒有設置進入到你的進程的task_struct// // 1.2 調用系統調用,將數據設置進內核// sigprocmask(SIG_SETMASK, &bset, &oset); // 我們已經把2好信號屏蔽了嗎?ok// // 2. 重復打印當前進程的pending 0000000000000000000000000// sigset_t pending;// int cnt = 0;// while (true)// {//     // 2.1 獲取//     int n = sigpending(&pending);//     if (n < 0)//         continue;//     // 2.2 打印//     PrintPending(pending);//     sleep(1);//     cnt++;//     // 2.3 解除阻塞//     if(cnt == 20)//     {//         cout << "unblock 2 signo" << endl;//         sigprocmask(SIG_SETMASK, &oset, nullptr); // 我們已經把2好信號屏蔽了嗎?ok//     }// }// // 3 發送2號 0000000000000000000000010return 0;
}

被注釋的代碼:

// 0. 設置2號信號(SIGINT)的處理函數
signal(2, handler);// 1. 先對2號信號進行屏蔽 --- 數據預備
sigset_t bset, oset;    // 在用戶棧上創建信號集
sigemptyset(&bset);     // 初始化為空集
sigemptyset(&oset);     // 保存舊的信號屏蔽字
sigaddset(&bset, 2);    // 只添加2號信號到屏蔽集
// 調用系統調用,將數據設置進內核
sigprocmask(SIG_SETMASK, &bset, &oset);// 2. 監控未決信號狀態
// 重復打印當前進程的pending 0000000000000000000000000
sigset_t pending;
int cnt = 0;
while (true)
{int n = sigpending(&pending);  // 獲取未決信號if (n < 0)continue;PrintPending(pending);         // 打印未決信號狀態sleep(1);cnt++;// 20秒后解除2號信號的屏蔽if(cnt == 20){cout << "unblock 2 signo" << endl;// 恢復原來的信號屏蔽字,即解除屏蔽sigprocmask(SIG_SETMASK, &oset, nullptr);}
}
// 3 發送2號 0000000000000000000000010

兩個場景的區別:

  1. 當前執行的代碼:
    • 屏蔽所有可屏蔽信號
    • 持續監控所有信號的未決狀態
    • 信號會一直保持在未決狀態
  2. 注釋掉的代碼:
    • 只屏蔽SIGINT(2號)信號
    • 設置了SIGINT的自定義處理函數
    • 20秒后解除屏蔽,讓信號能夠被處理
    • 可以觀察到SIGINT信號從未決變為已處理的過程

注釋中的重要說明:

  • task_struct:進程描述符,在內核中保存進程的信號屏蔽字
  • 信號集雖然在用戶棧上定義,但實際的屏蔽操作是在內核中完成
  • 通過注釋分步驟展示了信號屏蔽、監控和解除屏蔽的完整流程

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

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

相關文章

《手札·開源篇》從開源到商業化:中小企業的低成本數字化轉型路徑 ——以Odoo為數據中臺低成本實現售前售中一體化

某機電設備有限公司數字化轉型案例&#xff1a;以Odoo為數據中臺實現售前售中一體化 一、企業背景某機電設備有限公司在機電設備領域歷經多年發展&#xff0c;業務廣泛&#xff0c;涵蓋工業自動化設備、電力設備等產品的銷售與服務。隨著業務版圖不斷拓展&#xff0c;企業面臨…

筆試-業務邏輯4

應用 小明在玩一個數字加減游戲&#xff0c;輸入4個正整數&#xff1a;s、t、a、b&#xff0c;其中s>1&#xff0c;b<105&#xff0c;a!b。只使用加法或者減法&#xff0c;使得st。 每回合&#xff0c;小明用當前的數字&#xff0c;加上或減去一個數字&#xff1b;目前有…

Windows 中的 WSL:開啟你的 Linux 之旅

今天在安裝windows上安裝Docker Desktop的時候&#xff0c;遇到了WSL。下面咱們就學習下。 歡迎來到濤濤聊AI 一、什么是 WSL&#xff1f; WSL&#xff0c;全稱為 Windows Subsystem for Linux&#xff0c;是微軟為 Windows 系統開發的一個兼容層&#xff0c;它允許用戶在 Win…

編程題-電話號碼的字母組合(中等)

題目&#xff1a; 給定一個僅包含數字 2-9 的字符串&#xff0c;返回所有它能表示的字母組合。答案可以按 任意順序 返回。 給出數字到字母的映射如下&#xff08;與電話按鍵相同&#xff09;。注意 1 不對應任何字母。 解法一&#xff08;哈希表動態添加&#xff09;&#x…

python:如何播放 .spx 聲音文件

.spx 是 Speex音頻編解碼器的文件擴展名&#xff0c;它是一種開源的、免費的音頻編解碼器&#xff0c;主要用于語音壓縮和語音通信領域。spx 文件通常用于語音記錄、VoIP應用、語音信箱等場景。 .mp3 是一種廣泛使用的音頻格式&#xff0c;它采用了有損壓縮算法&#xff0c;可…

數據結構課程設計(三)構建決策樹

3 決策樹 3.1 需求規格說明 【問題描述】 ID3算法是一種貪心算法&#xff0c;用來構造決策樹。ID3算法起源于概念學習系統&#xff08;CLS&#xff09;&#xff0c;以信息熵的下降速度為選取測試屬性的標準&#xff0c;即在每個節點選取還尚未被用來劃分的具有最高信息增益的…

Vue3學習筆記-事件-4

一、事件處理 使用v-on或者后面加事件&#xff1a; <template><button v-on:click"addCount()">{{count}}</button> </template> 二、事件傳參 傳event&#xff1a; 不傳參時&#xff0c;默認自動接收 event 傳自定義參數時&#xff0c…

Node.js下載安裝及環境配置

目錄 一、下載 1. 查看電腦版本&#xff0c;下載對應的安裝包 2. 下載路徑下載 | Node.js 中文網 二、安裝步驟 1. 雙擊安裝包 2. 點擊Next下一步 3. 選擇安裝路徑 4. 這里我選擇默認配置&#xff0c;繼續Next下一步&#xff08;大家按需選擇&#xff09; 5. 最后inst…

k8s二進制集群之ETCD集群證書生成

安裝cfssl工具配置CA證書請求文件創建CA證書創建CA證書策略配置etcd證書請求文件生成etcd證書 繼續上一篇文章《負載均衡器高可用部署》下面介紹一下etcd證書生成配置。其中涉及到的ip地址和證書基本信息請替換成你自己的信息。 安裝cfssl工具 下載cfssl安裝包 https://github…

使用python實現與本地ollama部署的deepseek對話

專欄總目錄 按照ollama官方doc的example操作&#xff0c;沒有成功與本地ollama上的deepseek-r1:1.5b通訊后&#xff0c;發現vscode可以調用本地ollama上的deepseek模型。 為了實現與ollama上的deepseek模型通訊&#xff0c;我使用wireshark對本地回環地址進行偵聽后&#xff0c…

【大模型理論篇】最近大火的DeepSeek-R1初探系列1

1. 背景介紹 這一整個春節&#xff0c;被DeepSeek-R1刷屏。各種鋪天蓋地的新聞以及老板發的相關信息&#xff0c;著實感受到DeepSeek-R1在國外出圈的震撼。 DeepSeek推出了新的推理模型&#xff1a;DeepSeek-R1-Zero 和 DeepSeek-R1。DeepSeek-R1-Zero 是一個在沒有經過監督微調…

C++哈希表深度解析:從原理到實現,全面掌握高效鍵值對存儲

目錄 一、核心組件與原理 1. 哈希函數&#xff08;Hash Function&#xff09; 2. 沖突解決&#xff08;Collision Resolution&#xff09; 3. 負載因子&#xff08;Load Factor&#xff09;與擴容 二、C實現&#xff1a;std::unordered_map 1. 模板參數 2. 關鍵操作與復…

Pandoc, Zotero, JabRef 管理論文引用,生成參考文獻 | 撰寫論文 paper

書接上回&#xff0c;使用 Obsidian, Zotero, JabRef, Pandoc, Markup-Markdown | 撰寫論文 paper 管理論文引用&#xff0c;生成參考文獻 TL; DR導出 bibliography 文件JabRefZotero 參考文獻引用語法reference-docLinks TL; DR 安裝 pandoc v3.6.2. 使用一下命令&#xff0c…

為AI聊天工具添加一個知識系統 之85 詳細設計之26 批流一體式 與數據提取器

Q843、批流一體式 統一數據處理框架 "批流一體式統一數據處理框架" 這一概念通常指的是一種將批處理&#xff08;Batch Processing&#xff09;和流處理&#xff08;Stream Processing&#xff09;結合在一起的數據處理架構。它的目標是提供一個統一的框架&#xff…

深入理解 `box-sizing: border-box;`:CSS 布局的利器

深入理解 box-sizing: border-box;&#xff1a;CSS 布局的利器 默認行為示例代碼 使用 box-sizing: border-box;示例代碼 全局應用 box-sizing: border-box;示例代碼 實際應用場景1. 表單布局2. 網格布局 總結 在 CSS 中&#xff0c;box-sizing 屬性決定了元素的總寬度和高度是…

CSDN原力值提升秘籍:解鎖社區活躍新姿勢

在 CSDN 這個技術交流的大舞臺上&#xff0c;原力值不僅是個人活躍度的象征&#xff0c;更是開啟更多權益與福利的鑰匙。最近&#xff0c;我出于自身需求&#xff0c;一頭扎進了提升原力值的研究中&#xff0c;經過多方探索與資料整理&#xff0c;現在就迫不及待地把這些干貨分…

計算機網絡——流量控制

流量控制的基本方法是確保發送方不會以超過接收方處理能力的速度發送數據包。 通常的做法是接收方會向發送方提供某種反饋&#xff0c;如&#xff1a; &#xff08;1&#xff09;停止&等待 在任何時候只有一個數據包在傳輸&#xff0c;發送方發送一個數據包&#xff0c;…

2024美團春招硬件開發筆試真題及答案解析

目錄 一、選擇題 1、在 Linux,有一個名為 file 的文件,內容如下所示: 2、在 Linux 中,關于虛擬內存相關的說法正確的是() 3、AT89S52單片機中,在外部中斷響應的期間,中斷請求標志位查詢占用了()。 4、下列關于8051單片機的結構與功能,說法不正確的是()? 5、…

【C語言入門】解鎖核心關鍵字的終極奧秘與實戰應用(三)

目錄 一、auto 1.1. 作用 1.2. 特性 1.3. 代碼示例 二、register 2.1. 作用 2.2. 特性 2.3. 代碼示例 三、static 3.1. 修飾局部變量 3.2. 修飾全局變量 3.3. 修飾函數 四、extern 4.1. 作用 4.2. 特性 4.3. 代碼示例 五、volatile 5.1. 作用 5.2. 代碼示例…

Kafka分區策略實現

引言 Kafka 的分區策略決定了生產者發送的消息會被分配到哪個分區中&#xff0c;合理的分區策略有助于實現負載均衡、提高消息處理效率以及滿足特定的業務需求。 輪詢策略&#xff08;默認&#xff09; 輪詢策略是 Kafka 默認的分區策略&#xff08;當消息沒有指定鍵時&…