如何遮蔽SIGPIPE訊息

2021-10-03 20:58:14 字數 1696 閱讀 6554

最近被sigpipe訊息坑了很久.所以立志要一次性解決它.

對乙個對端已經關閉的socket呼叫兩次write, 第二次將會生成sigpipe訊號, 該訊號預設結束程序.

具體的分析可以結合tcp的」四次握手」關閉. tcp是全雙工的通道,可以看作兩條單工通道, tcp連線兩端的兩個端點各負責一條. 當對端呼叫close時, 雖然本意是關閉整個兩條通道, 但本端只是收到fin包. 按照tcp協議的語義, 表示對端只是關閉了其所負責的那一條單工通道, 仍然可以繼續接收資料. 也就是說,因為tcp協議的限制, 乙個端點無法獲知對端已經完全關閉.

對乙個已經收到fin包的socket呼叫read方法, 如果接收緩衝已空, 則返回0, 這就是常說的表示連線關閉. 但第一次對其呼叫write方法時, 如果傳送緩衝沒問題, 會返回正確寫入(傳送). 但傳送的報文會導致對端傳送rst報文, 因為對端的socket已經呼叫了close, 完全關閉, 既不傳送, 也不接收資料. 所以, 第二次呼叫write方法(假設在收到rst之後), 會生成sigpipe訊號, 導致程序退出.

那麼,我們如何遮蔽sigpipe訊息?

1. 使用signal函式

signal

(sigpipe, sig_ign)

;/* 忽略掉sigpipe訊息 */

signal函式是很老的東西,它由iso c定義,由於iso c不涉及多執行緒,程序組等,所以它對訊號的定義非常模糊,以致於對unix系統而言幾乎毫無用處.所以說,不推薦系統提供的signal函式.

如果你實在要使用signal的話,stevents老爺子用sigaction.函式給我們重新實現了一遍signal函式,我們比較推薦這個版本.這裡也順帶在這裡貼一下:

void

unix_error

(const

char

*msg)

/* unix-style error */

typedef

void

handler_t

(int);

handler_t *

signal

(int signum, handler_t *handler)

/* 用於註冊訊號處理函式 */

2. 訊號集

另外的方法也是有的,除了signal方法,其實我們也可以使用訊號集的方法.

我這裡給乙個函式:

void

blocksigno

(int signo)

然後呼叫:

blocksigno

(sigpipe)

;

即可.如果想具體了解這幾個函式,可以去看apue.

其實執行緒的遮蔽方法和單程序差不太多,不行,你可以看:

void

blocksigno

(int signo)

然後我們呼叫:

blocksigno

(sigpipe)

;

即可.當然,上面的**都做了簡化,沒有錯誤處理,你自己可以新增.

如何實現訊號遮蔽

linux中常見訊號量只有31個,所以程序pcb中表示常見的訊號量只用乙個位元組表示就夠了,程序得到了乙個訊號就是對應的乙個bit位由0改變為1。訊號被系統傳送給乙個程序,就是改變pcb中表示訊號量的位元組中對應的乙個bit位。程序收到某一訊號,相當於向表示訊號量的位元組中寫入了乙個訊號量。關於訊號...

如何遮蔽grep命令本身

我們經常會使用grep來過濾一些程序,但是grep的結果中總是包含grep本身命令,如下面所示 node74 ps ef grep monitorwatch vms 10356 1 0 09 17 00 00 00 bin sh monitorwatch.sh root 10974 10810 0 ...

Linux中如何遮蔽訊號

本篇文章主要學習linux的訊號處理機制,著重學習遮蔽訊號部分。遮蔽訊號處理的兩種方式類似於訊號的捕獲,一種方式是直接對其設定,另一種方式是先獲得描述符的掩碼,然後對其設定操作。本文主要參考自 嵌入式linux系統使用開發 作者何永琪,thanks.在linux系統中,如何處理某個程序傳送的乙個特定...