最近被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系統中,如何處理某個程序傳送的乙個特定...