




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第13章
捕獲13.1信號在Linux中,理解信號的概念是非常重要的。這是因為,信號被用于通過Linux命令行所做的一些常見活動中。例如,每當你按CTRL+C鍵來從命令行終結一個命令的執(zhí)行,你就使用了信號。每當你使用如下命令來結束一個進程時,你就使用了信號:$kill-9[PID]所以,至少知道信號的基本原理是非常有用的。這也就是本節(jié)我們要討論的內容。13.1.1Linux中的信號在Linux系統(tǒng)(以及其它類Unix操作系統(tǒng))中,信號被用于進程間的通訊。信號是一個發(fā)送到某個進程或同一進程中的特定線程的異步通知,用于通知發(fā)生的一個事件。從1970年貝爾實驗室的Unix面世便有了信號的概念,而現在它已經被定義在了POSIX標準中。對于在Linux環(huán)境進行編程的用戶或系統(tǒng)管理員來說,較好地理解信號的概念和機制是很重要的,在某些情況下可以幫助我們更高效地編寫程序。對于一個程序來說,如果每條指令運行正常的話,它會連續(xù)地執(zhí)行。但如果在程序執(zhí)行時,出現了一個錯誤或任何異常,內核就可以使用信號來通知相應的進程。信號同樣被用于通訊、同步進程和簡化進程間通訊,在Linux中,信號在處理異常和中斷方面,扮演了極其重要的角色。信號已經在沒有任何較大修改的情況下被使用了將近30年。13.1.1Linux中的信號在Linux系統(tǒng)(以及其它類Unix操作系統(tǒng))中,信號被用于進程間的通訊。信號是一個發(fā)送到某個進程或同一進程中的特定線程的異步通知,用于通知發(fā)生的一個事件。從1970年貝爾實驗室的Unix面世便有了信號的概念,而現在它已經被定義在了POSIX標準中。對于在Linux環(huán)境進行編程的用戶或系統(tǒng)管理員來說,較好地理解信號的概念和機制是很重要的,在某些情況下可以幫助我們更高效地編寫程序。對于一個程序來說,如果每條指令運行正常的話,它會連續(xù)地執(zhí)行。但如果在程序執(zhí)行時,出現了一個錯誤或任何異常,內核就可以使用信號來通知相應的進程。信號同樣被用于通訊、同步進程和簡化進程間通訊,在Linux中,信號在處理異常和中斷方面,扮演了極其重要的角色。信號已經在沒有任何較大修改的情況下被使用了將近30年。13.1.1Linux中的信號當一個事件發(fā)生時,會產生一個信號,然后內核會將事件傳遞到接收的進程。有時,進程可以發(fā)送一個信號到其它進程。除了進程到進程的信號外,還有很多種情況,內核會產生一個信號,比如文件大小達到限額、一個I/O設備就緒或用戶發(fā)送了一個類似于CTRL+C或CTRL+Z的終端中斷等。運行在用戶模式下的進程會接收信號。如果接收的進程正運行在內核模式,那么信號的執(zhí)行只有在該進程返回到用戶模式時才會開始。13.1.1Linux中的信號發(fā)送到非運行進程的信號一定是由內核保存,直到進程重新執(zhí)行為止。休眠的進程可以是可中斷的,也可以是不可中斷的。如果一個在可中斷休眠狀態(tài)的進程(例如,等待終端輸入的進程)收到了一個信號,那么內核會喚醒這個進程來處理信號。如果一個在不可中斷休眠狀態(tài)的進程收到了一個信號,那么內核會拖延此信號,直到該事件完成為止。13.1.1Linux中的信號當進程收到一個信號時,可能會發(fā)生以下三種情況:進程可能會忽略此信號。有些信號不能被忽略,而有些沒有默認行為的信號,默認會被忽略。進程可能會捕獲此信號,并執(zhí)行一個被稱為信號處理器的特殊函數。進程可能會執(zhí)行信號的默認行為。例如,信號15(SIGTERM)的默認行為是結束進程。當一個進程執(zhí)行信號處理時,如果還有其它信號到達,那么新的信號會被阻斷直到處理器返回為止。13.1.2信號的名稱和值每個信號都有“SIG”開頭的名稱,并定義為唯一的正整數。在Shell命令行提示符下,輸入“kill-l”命令,將顯示所有信號的信號值和相應的信號名。13.1.3Bash中的信號當沒有任何捕獲時,一個交互式BashShell會忽略SIGTERM和SIGQUIT信號。由Bash運行的非內部命令會使用Shell從其父進程繼承的信號處理程序。如果沒有啟用作業(yè)控制,異步執(zhí)行的命令會忽略除了有這些信號處理程序之外的SIGINT和SIGQUIT信號。由于命令替換而運行的命令會忽略鍵盤產生的作業(yè)控制信號SIGTTIN、SIGTTOU和SIGTSTP。13.1.3Bash中的信號默認情況下,Shell接收到SIGHUP信號后會退出。在退出之前,一個交互式的Shell會向所有的作業(yè),不管是正在運行的還是已停止的,重新發(fā)送SIGHUP信號。對已停止的作業(yè),Shell還會發(fā)送SIGCONT信號以確保它能夠接收到SIGHUP信號。若要阻止Shell向某個特定的作業(yè)發(fā)送SIGHUP信號,可以使用內部命令disown將它從作業(yè)表中移除,或是用“disown-h”命令仍阻止Shell向特定的作業(yè)發(fā)送SIGHUP信號,但并不會將特定的作業(yè)從作業(yè)表中移除。13.2進程13.2.1什么是進程進程是運行在Linux中的程序的一個實例。這是一個你之前就可能已經聽說過的基本定義。當你在Linux系統(tǒng)中執(zhí)行一個程序時,系統(tǒng)會為這個程序創(chuàng)建特定的環(huán)境。這個環(huán)境包含系統(tǒng)運行這個程序所需的任何東西。每當你在Linux中執(zhí)行一個命令,它都會創(chuàng)建,或啟動一個新的進程。比如,當你嘗試運行命令“l(fā)s-l”來列出目錄的內容時,你就啟動了一個進程。如果有兩個終端窗口顯示在屏幕上,那么你可能運行了同樣的終端程序兩次,這時會有兩個終端進程。每個終端窗口可能都運行了一個Shell,每個運行的Shell都分別是一個進程。當你從Shell調用一個命令時,對應的程序就會在一個新進程中執(zhí)行,當這個程序的進程執(zhí)行完成后,Shell的進程將恢復運行。13.2.1什么是進程操作系統(tǒng)通過被稱為PID或進程ID的數字編碼來追蹤進程。系統(tǒng)中的每一個進程都有一個唯一的PID。現在我們通過一個實例來了解Linux中的進程。我們在Shell命令行下執(zhí)行如下命令:$sleep10&[1]3324因為程序會等待10秒,所以我們快速地在當前Shell上查找任何進程名為sleep的進程:$ps-ef|grepsleepyantaol33245712cons117:11:46/usr/bin/sleep我們看到進程名為/usr/bin/sleep的進程正運行在系統(tǒng)中(其PID與我們在上一命令中得到的PID相同)。13.2.1什么是進程現在,我們嘗試并行地從3個不同的終端窗口運行上述的sleep命令,上述命令的輸出將類似如下所示:$ps-ef|grepsleepyantaol8965712cons117:16:51/usr/bin/sleepyantaol59245712cons117:16:52/usr/bin/sleepyantaol24245712cons117:16:50/usr/bin/sleep我們看到sleep程序的每一個實例都創(chuàng)建了一個單獨的進程。每個Linux進程還有另一個ID號碼,即父進程的ID(ppid)。系統(tǒng)中的每一個用戶進程都有一個父進程。命令“ps-f”就會列出進程的PID和PPID。此命令的輸出類似如下所示:$ps-fUIDPIDPPIDTTYSTIMECOMMANDyantaol4124228 cons0 21:37:09/usr/bin/psyantaol2281 cons0 21:32:23/usr/bin/bash13.2.1什么是進程你在Shell命令行提示符下運行的命令都把當前Shell的進程作為父進程。例如,你在Shell命令行提示符下輸入ls命令,Shell將執(zhí)行l(wèi)s命令,此時Linux內核會復制Shell的內存頁,然后執(zhí)行l(wèi)s命令。在Unix中,每一個進程是使用fork和exec方法創(chuàng)建的。然而,這種方法會導致系統(tǒng)資源的損耗。在Linux中,fork方法是使用寫時拷貝內存頁實現的,所以它導致的僅是時間和復制父進程的內存頁表所需的內存的損失,并且會為子進程創(chuàng)建一個唯一的任務結構。寫時拷貝模式在創(chuàng)建新進程時避免創(chuàng)建不必要的結構拷貝。例如,用戶在Shell命令行提示符下輸出ls命令,Linux內核將會創(chuàng)建一個Shell的子進程,即Shell的進程是父進程,而ls命令的進程是子進程,ls命令的進程會指向與此Shell相同的內存頁,然后子進程使用寫時拷貝技術執(zhí)行l(wèi)s命令。13.2.2前臺進程和后臺進程當你啟動一個進程時(運行一個命令),可以如下兩種方式運行該進程:前臺進程后臺進程默認情況下,你啟動的每一個進程都是運行在前臺。它從鍵盤獲取輸入并發(fā)送它的輸出到屏幕。當一個進程運行在前臺時,我們不能在同一命令行提示符下運行任何其它命令(啟動任何其它進程),因為在程序結束它的進程之前命令行提示符不可用。啟動一個后臺進程最簡單的方法是添加一個控制操作符‘&’到命令的結尾(關于進程在前臺和后臺之間切換的內容,請參見4.3.3節(jié))。13.2.2前臺進程和后臺進程例如,如下命令將啟動一個后臺進程:$sleep10&[1]5720$現在sleep命令被放在后臺運行。當Bash在后臺啟動一個作業(yè)時,它會打印一行內容顯示作業(yè)編號([1])和進程號(PID-5720)。當作業(yè)完成時,作業(yè)會發(fā)送類似如下的信息到終端程序,來顯示此作業(yè)已完成,其內容類似如下所示:[1]+Donesleep10將進程放在后臺運行的好處是:你可以繼續(xù)運行其它命令,而不需要等待此進程運行完成再運行其它命令。13.2.3進程的狀態(tài)每個Linux進程都有它自己的生命周期,比如,創(chuàng)建、執(zhí)行、結束和清除。每個進程也都有各自的狀態(tài),顯示進程中當前正發(fā)生什么。進程可以有如下幾種狀態(tài):D(不可中斷休眠狀態(tài))-進程正在休眠并且不能恢復,直到一個事件發(fā)生為止。R(運行狀態(tài))-進程正在運行。S(休眠狀態(tài))-進程沒有在運行,而在等待一個事件或是信號。T(停止狀態(tài))-進程被信號停止,比如,信號SIGINT或SIGSTOP。Z(僵死狀態(tài))-標記為<defunct>進程是僵死的進程,它們之所以殘留是因為它們的父進程適當地銷毀它們。如果父進程退出,這些進程將被init進程銷毀。13.2.3進程的狀態(tài)若要查看指定進程的狀態(tài),可以使用如下命令:$ps-CprocessName-opid=,cmd,stat例如:$ps-Csleep-opid=,cmd,statCMDSTAT9434sleep20S13.2.4實例:怎樣查看進程通過前面章節(jié)的一些實例的學習,想必你已經知道了使用ps命令可以查看進程的信息,但除了ps命令,我們還可以使用pstree命令和pgrep命令查看當前進程的信息。使用ps命令,可以查看當前的進程。默認情況下,ps命令只會輸出當前用戶并且是當前終端(比如,當前Shell)下調用的進程的信息。13.2.5實例:向進程發(fā)送信號我們可以使用鍵盤或pkill命令、kill命令和killall命令向進程發(fā)送各種信號。在Bash下,我們可以使用鍵盤發(fā)送如下信號。組合鍵含義Ctrl+C中斷信號,發(fā)送SIGINT信號到運行在前臺的進程Ctrl+Y延時掛起信號,使運行的進程在嘗試從終端讀取輸入時停止??刂茩喾祷亟oShell,使用戶可以將進程放在前臺或后臺,或殺掉該進程Ctrl+Z掛起信號,發(fā)送SIGTSTP信號到運行的進程,由此將其停止,并將控制權返回給Shell13.2.5實例:向進程發(fā)送信號大多數主流的Shell,包括Bash,都有內置的kill命令。Linux系統(tǒng)中,也有kill命令,即/bin/kill。如果使用/bin/kill,則系統(tǒng)可能會激活一些額外的選項,比如,殺掉不是你自己的進程,或指定進程名作為參數,類似于pgrep和pkill命令。不過兩種kill命令默認都是發(fā)送SIGTERM信號。當準備殺掉一個進程或一連串的進程時,我們的常識是嘗試發(fā)送最安全的信號開始,即SIGTERM信號。以這種方式,關心正常停止運行的程序,當它收到SIGTERM信號時,有機會按照已經設計好的流程執(zhí)行,比如,清理和關閉打開的文件。如果你發(fā)送一個SIGKILL信號到進程,你將消除進程先清理而后關閉的機會,而這可能會導致不幸的結果。但如果一個有序地終結不管用,那么發(fā)送SIGINT或SIGKILL信號就可能是唯一的方法了。例如,當一個前臺進程使用Ctrl+C殺不掉時,那最好就使用命令“kill-9PID”了。13.2.5實例:向進程發(fā)送信號kill命令可以發(fā)送多種信號到進程。特別有用的信號包括:SIGHUP(1)SIGINT(2)SIGKILL(9)SIGCONT(18)SIGSTOP(19)在Bash中,信號名或信號值都可作為kill命令的選項,而作業(yè)號或進程號則作為kill命令的參數。13.2.6關于子Shell子Shell是由Shell或Shell腳本運行的子進程。當你在Shell命令行提示符下,運行一個Shell腳本時,它會創(chuàng)建一個叫做子Shell的新進程,你的腳本將會使用這個子Shell來運行。子Shell是命令處理程序(提供給你命令行提示符的Shell或是一個xterm窗口)的一個單獨實例。就像你的命令在命令行提示符下被解釋,類似地,腳本批處理一連串命令。實際上,每個運行的Shell腳本都是父Shell的子進程。Shell腳本可以自己啟動子進程。這些子Shell讓腳本可以做并行處理,實際上是同時執(zhí)行多個子任務。13.3捕獲到目前為止,我們在本書所見的腳本中還沒有需要信號處理功能的,因為它們的內容相對比較簡單,執(zhí)行時間很短,而且不會創(chuàng)建臨時文件。而對于較大的或者更復雜的腳本來說,如果腳本具有信號處理機制可能就比較有用了。當我們設計一個大且復雜的腳本時,考慮到當腳本運行時出現用戶退出或系統(tǒng)關機會發(fā)生什么,是很重要的。當這樣的事件發(fā)生時,一個信號將會發(fā)送到所有受影響的進程。相應地,這些進程的程序可以采取一些措施以確保程序正常有序地終結。比如說,我們編寫了一個會在執(zhí)行時生成臨時文件的腳本。在好的設計過程中,我們會讓腳本在執(zhí)行完成時刪除這些臨時文件。同樣聰明的做法是,如果腳本接收到了指示程序將提前結束的信號,也應刪除這些臨時文件。接下來,就讓我們開始學習,如何在腳本中進行這些處理。13.3.1trap語句Bash的內部命令trap,讓我們可以在Shell腳本內捕獲特定的信號并對它們進行處理。trap命令的語法如下所示:$trapcommandsignal[signal…]上述語法中,command可以是一個腳本或是一個函數。signal即可以用信號名,也可以用信號值指定。你可以不指定任何參數,而直接使用trap命令,它將會打印與每個要捕獲的信號相關聯的命令的列表。13.3.1trap語句當Shell收到信號signal(s)時,command將被讀取和執(zhí)行。比如,如果signal是0或EXIT時,command會在Shell退出時被執(zhí)行。如果signal是DEBUG時,command會在每個命令后被執(zhí)行。signal也可以被指定為ERR,那么每當一個命令以非0狀態(tài)退出時,command就會被執(zhí)行(注意,當非0退出狀態(tài)來自一個if語句部分,或來自while、until循環(huán)時,command不會被執(zhí)行)。下面我們通過幾個簡單的實例來學習trap命令的用法。13.3.2實例:使用trap語句捕獲信號通過前面內容的學習,我們已經知道,信號多用于以友好的方式結束一個進程的執(zhí)行,既允許進程在退出之前有機會做一些清理工作。然而,信號同樣還可用于其它用途。例如,當終端窗口的大小改變時,在此窗口中運行的Shell都會接收到信號SIGWINCH。通常,這個信號是被忽略的,但是,如果一個程序關心窗口大小的變化,它就可以捕獲這個信號,并用特定的方式處理它。注意:除SIGKILL信號以外,其它任何信號都可以被捕獲并通過調用C函數signal處理。接下來,我就以一個腳本為實例演示捕獲并處理SIGWINCH信號。13.3.3實例:移除捕獲如果我們在腳本中應用了捕獲,我們通常會在腳本的結尾處,將接收到信號時的行為處理重置為默認模式。重置(移除)捕獲的語法如下所示:$trap-signal[signal…]從上述語法中可以看出,使用破折號作為trap語句的命令參數,就可以移除信號的捕獲。下面,我們以腳本trap_reset.sh為例,來學習如何在腳本中移除先前定義的捕獲。13.4小結下面我們總結一下本章所學的主要知識:在Linux系統(tǒng)和其它類Unix或Unix操作系統(tǒng)中,信號被用于進程間的通訊。信號是一個發(fā)送到某個進程或同一進程中的特定線程的異步通知,用于通知發(fā)生的一個事件。在Linux中,信號在處理異常和中斷方面,扮演了極其重要的角色。當一個事件發(fā)生時,會產生一個信號,然后內核會將事件傳遞到接收的進程。運行在用戶模式下的進程會接收信號。如果接收的進程正運行在內核模式,那么信號的執(zhí)行只有在該進程返回到用戶模式時才會開始。13.4小結當進程收到一個信號時,可能會發(fā)生以下三種情況:進程可能會忽略此信號。有些信號不能被忽略,而有些沒有默認行為的信號,默認會被忽略。進程可能會捕獲此信號,并執(zhí)行一個被稱為信號處理器的特殊函數。進程可能會執(zhí)行信號的默認行為。例如,信號15(SIGTERM)的默認行為是結束進程。在Shell命令行提示符下,輸入“kill-l”命令,可以顯示所有信號的信號值和相應的信號名。由Bash運行的非內部命令會使用Shell從其父進程繼承的信號處理程序。默認情況下,Shell接收到SIGHUP信號后會退出。在退出之前,一個交互式的Shell會向所有的作業(yè),不管是正在運行的還是已停止的,重新發(fā)送SIGHUP
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工業(yè)控制計算機在水處理自動化中的應用考核試卷
- 前臺文員的電話禮儀培訓計劃
- 公司生產工作計劃提升供應鏈效能
- 品牌成長的動力與維持策略計劃
- 中學課程教學計劃
- 《基礎化學分析實驗》課程教學大綱
- 前臺工作中的自我提升計劃
- 從失敗中學習的工作計劃
- AI技術在各領域的應用與發(fā)展前景
- 督灸技術操作流程圖及考核標準
- 第五章產前檢查及高危妊娠監(jiān)測90課件
- 專利共有合同范例
- 2025年上半年山西交控集團所屬路橋集團交投集團招聘800人易考易錯模擬試題(共500題)試卷后附參考答案
- 外周靜脈血管解剖知識
- 《基于舞弊風險因子的輝山乳業(yè)公司財務舞弊案例探析》15000字(論文)
- 《教育強國建設規(guī)劃綱要(2024-2035年)》解讀與培訓
- 2024年03月中國工商銀行湖南分行2024年度春季校園招考筆試歷年參考題庫附帶答案詳解
- 員工離職面談記錄表范本
- 2025年青島市技師學院招考聘用48人高頻重點提升(共500題)附帶答案詳解
- 2024年08月澳門2024年中國銀行澳門分行校園招考筆試歷年參考題庫附帶答案詳解
- 110KV-GIS設備技術要求
評論
0/150
提交評論