2010-05-18 54 views
1

我在Linux內核2.4中實現用戶線程,並且我使用ualarm來調用線程之間的上下文切換。使用sigprocmask來實現鎖

我們有一個要求,我們的線程庫的函數應該不會被線程的上下文切換機制中斷,所以我查看了阻塞信號,並瞭解到使用sigprocmask是執行此操作的標準方法。

但是,它看起來像我需要做不少來實現這一點:

sigset_t new_set, old_set; 

sigemptyset(&new_set); 
sigaddset(&new_set, SIGALRM); 
sigprocmask(SIG_BLOCK, &new_set, &old_set); 

此塊SIGALARM但它確實這3個函數調用!這些功能運行所需的時間會很多,包括髮送的信號。 最好的辦法,我不得不減輕這是暫時禁用ualarm,像這樣:

sigset_t new_set, old_set; 

time=ualarm(0,0); 
sigemptyset(&new_set); 
sigaddset(&new_set, SIGALRM); 
sigprocmask(SIG_BLOCK, &new_set, &old_set); 
ualarm(time, 0); 

這是除了這種感覺冗長的罰款。沒有更好的方法來做到這一點?

回答

1

由於WhirlWind指出,信號設置功能是相當輕量級,甚至可以實現爲宏;你也可以只保留一個只包含SIGALRM的信號集並重新使用它。

無論如何,它實際上並沒有如果信號在sigaddset()sigemptyset()呼叫發生的那樣 - new_setold_set可變的(大概)線程本地和關鍵部分沒有進入到後sigprocmask()回報。

1

您會發現sigemptyset()sigaddset()signals.h只是宏或內聯函數,因此它們在您的代碼中內聯執行。當你打電話時只需使用堆棧變量。

但是,爲什麼不在代碼的單線程啓動部分執行此操作?我也懷疑函數調用sigprocmask將是原子。阻止信號並不意味着您的代碼將不會被中斷。順便說一下,我不確定你是如何使用ualarm的,但是如果你在第一次調用它時沒有捕獲或忽略SIGALARM,你可能會終止你的過程。

+0

」阻止信號並不意味着您的代碼將不可中斷。「是的,我的意思是我正在執行的上下文切換機制不可中斷(更新的問題)。 ualarm每THREAD_TIME_SLICE關閉,處理程序將執行切換到另一個線程。 – EpsilonVector 2010-05-18 01:47:52

0

sigprocmask()是進入內核級別並實際改變信號屏蔽狀態的唯一函數。其他函數只是在調用sigprocmask或將該函數傳遞給另一個與信號相關的函數之前設置掩碼的操作函數。 「