最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux中的信號(注冊,注銷,處理,阻塞)

 更新時間:2024年02月12日 17:04:22   作者:風吹雨淋  
這篇文章主要介紹了Linux中的信號(注冊,注銷,處理,阻塞),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

未決:pending(漢語翻譯:待定,即將發(fā)生)

  • 信號產生但沒有被處理,pending表0變1,表示進程收到對應信號(準確的來說叫信號寫入)
  • 阻塞,為了攔截對應信號做出對應的處理動作。不想處理某些信號,攔不住別人給進程發(fā)
  • 信號待定是可以隨時遞達(被處理),如果沒有被阻塞,信號會在合適的時候遞達(被處理)
  • 什么叫合適的時候:從內核態(tài)切換到用戶態(tài)時進行信號的檢測和處理
  • 如果信號阻塞,該信號永遠處于未決狀態(tài)
  • 總之pending表就是隨時能處理信號,一旦設置了阻塞,只有解除阻塞才能處理信號

信號注冊

信號注冊:在進程中做標記,讓進程能夠知道自己收到某個信號,官方說法操作系統(tǒng)內核給進程發(fā)送信號的過程,這個過程稱為注冊

  • PCB中有一個pending未決(沒有被處理)信號的集合(是一個位圖結構),標記進程收到了某個信號
  • PCB中有一個sigqueue鏈表(實質是一個雙向鏈表),進程每收到一個信號,就是給該鏈表中添加一個對應信號的節(jié)點,并且修改位圖,將信號值對應位置置1

非可靠信號注冊:

  • 如果沒有收到信號則注冊(添加節(jié)點,位圖置1)
  • 如果之前收到了信號還未處理,則什么都不做(丟棄)

可靠信號注冊:

  • 不管位圖是否置1(是否已經注冊,還沒處理),都會添加一個信號節(jié)點

可以通過sigqueue函數(shù)在發(fā)送信號的同時攜帶數(shù)據(jù)

信號注銷

什么是注銷:

  • 在信號被處理之前,消除信號存在的痕跡
  • 主要防止信號被重復處理

非可靠信號的注銷:

刪除信號的信息節(jié)點,位圖置0

可靠信號的注銷:

刪除信號的一個信息節(jié)點,當前沒有相同節(jié)點則位圖置0

信號處理

處理就是調用信號的處理函數(shù)

有三種處理方式

默認處理:系統(tǒng)中已經定義好了處理方式

忽略處理:空的處理方式

SIGCHLD:子進程再退出時給父進程發(fā)送一個SIGCHLD信號,父進程對于該信號的處理方式是忽略處理 該信號對于所有進程而言都是忽略處理

自定義處理:自己定義一個處理函數(shù),替換掉處理函數(shù)

自定義處理函數(shù)signal

用handler函數(shù),替換signum信號當前的處理函數(shù)

自定義信號的捕捉流程(捕捉流程:從用戶態(tài)進入內核態(tài),找到信號并處理的過程)

進入內核的原因:

  • 系統(tǒng)調用函數(shù)
  • 中斷
  • 進程異常

當前執(zhí)行流在用戶態(tài)收到信號,不能立即處理信號,而是從用戶態(tài)切換到內核態(tài)時處理

進入內核后,執(zhí)行流并不知道要處理信號,而是執(zhí)行一些功能當要從內核態(tài)返回到用戶態(tài),一定會調用do_signal函數(shù)判斷當前進程有無收到信號,收到則立即處理,沒有直接返回到用戶態(tài)

如果有信號就執(zhí)行信號對應動作

如果是自定義處理方式,會從內核態(tài)切換到用戶態(tài)執(zhí)行自定義函數(shù),調用sigreturn函數(shù)再次進入到內核(不能以內核身份執(zhí)行用戶寫的自定義代碼)

再去調用dosignal判斷是否有其它信號需要處理

信號阻塞

阻塞(阻塞不是在處理信號)

信號被阻塞后依然會注冊,但是暫時不處理(直到被解除阻塞)

PCB中有個block阻塞信號集合,哪個信號被添加到block阻塞集合中,表示收到信號但暫時不處理

更改或獲取進程的信號block表(將信號集合設置進內核)

int sigprocmask(int how, const sigset_t* set, sigset_t* oset)

how:對PCB中信號阻塞集合進行的操作

SIG_BLOCK:block|=set

把set集合中的信號添加到block集合中,阻塞set集合中的信號

SIG_UNBLOCK:block&=~set

解除

SIG_SETMASK:block=set

重新設置block表

oldset將修改前block集合中的信息添加到old中,便于還原

是輸出型參數(shù),將原block返回,不想返回設置為NULL

要屏蔽2號信號,將2號信號添加到set中

set是輸入型參數(shù)

  • 函數(shù)在阻塞指定信號時,就要傳進去一個集合, 意味著要將所有的信號添加到一個集合中
  • 所以要先定義一個信號集合的變量sigset_t
  • 通過sigsetempty(sigset* set)先將集合中的數(shù)據(jù)清空
  • 通過sigaddset(sigset_t* set, int sugnum)----將signum添加到set集合中(單個添加)
  • 通過sigfillset(sigset_t *set)------------------------將所有信號添加到set中
  • 通過sigdelset(sigset_t *set, int signum)----移除指定信號
  • 通過sigismember(sigset_t *set, int signum)–按段信號signum是(返回1)否(-1)在set信號集合中

9號和19號不能被阻塞,忽略,自定義

僵尸進程是已經死了的

SIGPIPE

  • 管道讀端關閉,繼續(xù)寫,會在write會觸發(fā)異常

SIGCHLD

  • 子進程退出時給父進程發(fā)送的信號
  • 這個信號的默認處理方式是忽略,因此未對子進程退出做出處理

修改SIGCHLD的默認處理方法(讓回調函數(shù)內部wait子進程)其實并不合理

因為該信號是非可靠信號,大量子進程同時退出,發(fā)出的多個非可靠信號可能只注冊了一次

可直接顯示忽略,明確告訴OS,子進程退出我不關心,直接把資源回收

signal(SIGCHLD, SIG_IGN)

或者在回調函數(shù)內部,使用waitpid循環(huán)等待每一個子進程退出的信號

int sigpending(sigset_t *set)

獲取當前進程的pending信號集(輸出型參數(shù)),放入set集合中

PCB如何獲取signal函數(shù)使用自定義信號

在PCB有一個結構體指針struct sighand_struct* sighand,該指針指向結構體sighand_struct;

該結構體中有一個struct k_sigaction action[_NSIG]數(shù)組,數(shù)組中的每個元素是一個多重嵌套結構體,如圖

  • action數(shù)組中一個元素就保存了一個信號對應的處理方式,
  • 例如,2號信號對應一個action數(shù)組中的元素,2號信號的處理方式就保存在_sighander_t類型的變量中
  • 該類型的變量保存了三種數(shù)據(jù),就是上述的三種信號處理方式,默認處理、忽略處理、自定義處理

PCB與signal函數(shù)的關系

  • 在調用signal函數(shù),參數(shù)sighandler保存了新函數(shù)地址,該新地址是傳送給PCB中action數(shù)組的元素,該元素內容被修改
  • 就通過signal函數(shù)改變了2號信號的處理方式,
  • 當進程在處理2號時通過PCB一步步找到action數(shù)組找到2號信號的處理方式,發(fā)現(xiàn)其處理方式是自定義的函數(shù)
  • 從而調用自定義的函數(shù)

sigaction函數(shù)

修改指定信號的處理動作

改變action數(shù)組元素中第二個結構體,而signal函數(shù)只是改變該結構體下的一個成員變量

需要配合其他函數(shù)使用

sa_handler是信號的處理方式

sa_mask:信號正在被處理時,內存會將當前信號加入到信號屏蔽字,信號返回時回復成原來的信號屏蔽字

這樣保證了在處理某個信號時,此信號再次產生就會被阻塞直到當前處理結束

需要用到的清空函數(shù)(上圖黑色部分指錯了):

可重入函數(shù)

現(xiàn)有一個鏈表需要進行頭插,在執(zhí)行頭插函數(shù)時,代碼進入內核在退出時發(fā)現(xiàn)一個信號,該信號也是在執(zhí)行頭插代碼

這樣會發(fā)生內存泄漏,信號所調用的頭插函數(shù)插入的節(jié)點找不到了,這種函數(shù)就稱為不可重入函數(shù)

如果只是訪問變量或者參數(shù),則稱為可重入函數(shù)

volatile關鍵字

在編譯的時候,全局變量flags只進行邏輯運算,編譯器會自動將其優(yōu)化,將變量優(yōu)化到寄存器中

不從內存中讀取,而信號修改flag的值只是對內存值修改

防止編譯時因優(yōu)化,使CPU不從內存中取值,而從寄存器中取值

sigchld

子進程退出時不是默默的退出

子進程退出時會給父進程發(fā)送SIGCHLD信號,該信號的默認處理方式是IGN(忽略)

無論是阻塞還是非阻塞,都需要父進程主動去詢問

則現(xiàn)在提前告訴子進程,子進程死亡時發(fā)消息,父進程收到后回收資源即可

所以通過signal函數(shù)修改SIGCHLD信號的處理方式,改為wait等待子進程即可

前七個子進程結束,通過waitpid等待成功,在等待第八個子進程退出時,父進程會阻塞在waitpid函數(shù)處

通過sigaction將SIGCHLD的處理動作設置為SIG_IGN,這樣fork出來的子進程在終止時會自動清理掉,不會產生僵尸進程

這兩個忽略其實沒有任何區(qū)別

意義:手動設置了SIG_IGN,除了修改父進程,子進程也會受影響,讓子進程退出不給對應父進程發(fā)送信號

在OS層面上,手動設置信號,會在設置子進程時不給父進程發(fā)消息,并自動釋放

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Linux之路由轉發(fā)和SNAT的應用方式

    Linux之路由轉發(fā)和SNAT的應用方式

    這篇文章主要介紹了Linux之路由轉發(fā)和SNAT的應用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Linux如何查看操作系統(tǒng)版本號

    Linux如何查看操作系統(tǒng)版本號

    文章介紹了在Linux主機上查看操作系統(tǒng)版本號的幾種方法,包括使用`cat /etc/redhat-release`、`uname -a`、`rpm -qa | grep lsb`和`lsb_release -a`等命令,這些方法適用于不同的Linux發(fā)行版,如CentOS、Ubuntu等
    2024-11-11
  • 如何在Linux中route?add命令添加路由(Linux?route)

    如何在Linux中route?add命令添加路由(Linux?route)

    route?add命令是用于管理Linux操作系統(tǒng)網絡路由,允許用戶添加、刪除或修改網絡路由表中的條目,在Linux系統(tǒng)上添加靜態(tài)路由,靜態(tài)路由是手動配置的路由,它指定了數(shù)據(jù)包從一個網絡到達另一個網絡的路徑,通過添加靜態(tài)路由,可實現(xiàn)網絡分段、轉發(fā)和通信等
    2024-06-06
  • linux服務器磁盤滿了的三種解決方案

    linux服務器磁盤滿了的三種解決方案

    這篇文章主要給大家介紹了linux服務器磁盤滿了的三種解決方案,文章通過圖文結合的形式給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-04-04
  • Linux環(huán)境使用crontab命令設置定時周期性執(zhí)行任務【含php執(zhí)行代碼】

    Linux環(huán)境使用crontab命令設置定時周期性執(zhí)行任務【含php執(zhí)行代碼】

    這篇文章主要介紹了Linux環(huán)境使用crontab命令設置定時周期性執(zhí)行任務,結合實例形式較為詳細的分析了crontab命令的功能、應用場景及相關操作注意事項,并附帶了php執(zhí)行代碼供大家參考,需要的朋友可以參考下
    2019-07-07
  • putty使用密鑰登陸OpenSSH配置方法(圖文詳解)

    putty使用密鑰登陸OpenSSH配置方法(圖文詳解)

    這篇文章主要介紹了putty使用密鑰登陸OpenSSH配置方法(圖文詳解),需要的朋友可以參考下
    2015-07-07
  • 淺談Linux中的chattr與lsattr命令

    淺談Linux中的chattr與lsattr命令

    下面小編就為大家?guī)硪黄獪\談Linux中的chattr與lsattr命令。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • linux系統(tǒng)磁盤存儲擴容根目錄邏輯卷擴容詳解

    linux系統(tǒng)磁盤存儲擴容根目錄邏輯卷擴容詳解

    文章詳細介紹了如何將新增磁盤增加到Linux根目錄,包括區(qū)分邏輯卷和物理卷、查看新增磁盤信息、對新磁盤進行分區(qū)和格式化、創(chuàng)建物理卷、擴展卷組、擴展邏輯卷、擴展文件系統(tǒng)以及查看擴容效果
    2026-01-01
  • Linux上查看用戶創(chuàng)建日期的幾種方法總結

    Linux上查看用戶創(chuàng)建日期的幾種方法總結

    在Linux系統(tǒng)中,如何找到用戶創(chuàng)建的時間呢?下面這篇文章就來給大家介紹了關于在Linux上如何查看用戶創(chuàng)建日期的幾種方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-05-05
  • 教你一步一步在linux中正確的安裝Xcache加速php

    教你一步一步在linux中正確的安裝Xcache加速php

    這篇文章主要介紹了教你一步一步在linux中正確的安裝Xcache加速php,需要的朋友可以參考下
    2017-04-04

最新評論

曲靖市| 金湖县| 洪洞县| 凌云县| 正定县| 乌拉特中旗| 鄂托克旗| 明溪县| 黄冈市| 威信县| 沙田区| 青浦区| 镇赉县| 繁昌县| 开封市| 潜山县| 兰西县| 建阳市| 德兴市| 东海县| 石家庄市| 康乐县| 凯里市| 贵港市| 英山县| 翼城县| 海南省| 漳平市| 鄯善县| 卢氏县| 崇礼县| 资源县| 山阴县| 阿坝县| 沂水县| 克什克腾旗| 宝鸡市| 剑阁县| 南通市| 南川市| 乌拉特前旗|