iOS Mach異常和signal訊號

2021-09-11 12:04:29 字數 3833 閱讀 6091

1. ios mach異常

1.1 xnu

darwin是mac os和ios的作業系統,而xnu是darwin作業系統的核心部分。xnu是混合核心,兼具單核心和微核心的特性,而mach即為其微核心。

darwin作業系統和macos、ios系統版本號的對應如上圖所示,mac可執行下述命令檢視darwin版本號。

system_profiler spsoftwaredatatype

1.2 mach

mach:[mʌk],作業系統微核心,是許多新作業系統的設計基礎。

mach微核心中有幾個基礎概念:

tasks,擁有一組系統資源的物件,允許"thread"在其中執行。

threads,執行的基本單位,擁有task的上下文,並共享其資源。

ports,task之間通訊的一組受保護的訊息佇列;task可對任何port傳送/接收資料。

message,有型別的資料物件集合,只可以傳送到port。

1.3 模擬mach message傳送

// 核心中建立乙個訊息佇列,獲取對應的port mach_port_allocate(); // 授予task對port的指定許可權 mach_port_insert_right(); // 通過設定引數:mach_rsv_msg/mach_send_msg用於接收/傳送mach message mach_msg();

下述**模擬向mach port傳送message,接收message後做處理:

2018-02-27 09:33:37.797435+0800 ***[54456:5198921] create a port: 41731 2018-02-27 09:33:37.797697+0800 ***[54456:5198921] send a mach message: [100]. 2018-02-27 09:33:37.797870+0800 ***[54456:5199525] receive a mach message:[100], remote_port: 0, local_port: 41731, exception code: 28672

// 建立mach port並監聽訊息 + (mach_port_t)createportandaddlistener + (void)setmachportlistener:(mach_port_t)mach_port mach_msg_id_t msg_id = mach_message.head.msgh_id; mach_port_t remote_port = mach_message.head.msgh_remote_port; mach_port_t local_port = mach_message.head.msgh_local_port; nslog(@"receive a mach message:[%d], remote_port: %d, local_port: %d, exception code: %d", msg_id, remote_port, local_port, mach_message.exception); abort(); } }); } // 向指定mach port傳送訊息 + (void)sendmachportmessage:(mach_port_t)mach_port

1.4 捕獲mach異常

2018-02-27 09:52:11.483076+0800 ***[55018:5253531] create a port: 23299 2018-02-27 09:52:14.484272+0800 ***[55018:5253531] ********** make a [bad mem access] now. ********** 2018-02-27 09:52:14.484477+0800 ***[55018:5253611] receive a mach message:[2405], remote_port: 23555, local_port: 23299, exception code: 1

+ (void)createandsetexceptionport // 構造bad mem access crash - (void)makecrash

1.5 runloop

mach port的應用不止於核心級別,在cocoa foundation和core foundation層同樣有其應用,比如說:runloop。

runloop sources分兩類:

1.input sources

port-based sources

custom input sources

2.timer sources

其中port-based sources即基於mach port,在runloop中完成訊息傳遞。

上述的mach api為核心層透出介面,cocoa foundation和core foundation層分別封裝了mach port的介面供呼叫,參考:

2. signal訊號

signal是一種軟中斷訊號,提供非同步事件處理機制。signal是程序間相互傳遞資訊的一種粗糙方法,使用場景:

程序終止相關;

終端互動;

這裡我們主要考慮系統遇到不可恢復的錯誤時即crash時,訊號相關的應用。signal訊號處理是unix作業系統機制,所以android平台理論上也是使用的,可以基於signal來捕獲android native crash。

2.1 signal註冊和處理

signal()

#import;

註冊signal handler;

呼叫成功時,會移除signo訊號當前的操作,以handler指定的新訊號處理程式替代;

訊號處理函式返回void,因為沒有地方給該函式返回。註冊自定義訊號處理函式,構造crash後,發出訊號並執行自定義訊號處理邏輯。

【附】:xcode debug執行時,新增斷點,在crash觸發前,執行pro hand -p true -s false sigabrt命令。

// 設定自定義訊號處理函式 + (void)setsignalhandler static void test_signal_handler(int signo) // 構造nsrangeexception異常,觸發sigabrt訊號傳送 - (void)makecrash

2.2 lldb debugger

// process handle縮寫 pro hand

// option: // -p: pass // -s: stop // -n: notify pro hand -option false 訊號名 // 例:sigabrt訊號處理在lldb不停止,可繼續拋到使用者層 pro hand -s false sigabrt

2.3 可重入

向核心傳送訊號時,程序可能執行到**的任意位置,例:程序在執行重要操作,中斷後可能產生不一致狀態,或程序正在處理另一訊號。因此要確保訊號處理程式只執行可重入操作:

2.4 高階訊號處理

signal()函式非常基礎,只提供了最低限度的訊號管理的標準。而sigaction()系統呼叫,提供更強大的訊號管理能力。當訊號處理程式執行時,可以用來阻塞特定訊號的接收,也可以用來獲取訊號傳送時各種作業系統和程序狀態的資訊。

// 設定自定義訊號處理函式 + (void)setsignalhandlerinadvance static void test_signal_action_handler(int signo, siginfo_t *si, void *ucontext) ", si->si_signo, si->si_errno, si->si_code, si->si_pid, si->si_uid, si->si_status, si->si_value.sival_int); }

3. 參考

wiki - mach

漫談ios crash收集框架

the lldb debugger

wm中獲取,roaming 狀態和signal

int getdialupsignalstrength int dwsignal byte dsignal 0 dword type 1 reg dword dword cbdata 1 128 ret regqueryvalueex hkey,t signal strength raw null,...

異常和異常處理

程式執行遇到兩種錯誤 1.error 錯誤 致命錯誤,無法恢復執行 2.exception 異常 通過修正,繼續執行。異常類常用方法 1.tostring 返回描述異常物件資訊字串 2.getmessage 返回描述物件詳細資訊 處理方法 1.try catch finally 1 try中包涵可能...

關於異常和異常捕獲。

異常即非正常狀態,主要包括書寫或語法上的錯誤導致直譯器無法正常執行。異常描述 importerror 匯入模組 物件失敗 indexerror 序列中沒有此索引 index keyerror 對映中沒有這個鍵 nameerror 未宣告 初始化物件 沒有屬性 syntaxerror python 語...