如何設計一個C/C++程序,以便在接收到中斷信號後保存一些數據。中斷正在運行程序並保存數據
我有一個長時間運行的程序,可能需要在完成運行之前殺死(例如,通過按Ctrl-C)。當遇害(而不是結論)程序應該能夠將一些變量保存到磁盤。我有幾本大型Linux書籍,但不知道從哪裏開始。食譜食譜會非常有幫助。
謝謝。
如何設計一個C/C++程序,以便在接收到中斷信號後保存一些數據。中斷正在運行程序並保存數據
我有一個長時間運行的程序,可能需要在完成運行之前殺死(例如,通過按Ctrl-C)。當遇害(而不是結論)程序應該能夠將一些變量保存到磁盤。我有幾本大型Linux書籍,但不知道從哪裏開始。食譜食譜會非常有幫助。
謝謝。
要做到這一點,您需要讓程序監視某些東西,例如全局變量,這會告訴他停止正在執行的操作。
例如,假設您的長時間運行的程序執行一個循環,你可以這樣做:
g_shouldAbort = 0;
while(!finished)
{
// (do some computing)
if (g_shouldAbort)
{
// save variables and stuff
break; // exit the loop
}
}
與g_shouldAbort定義爲全局揮發性變量,像:
static volatile int g_shouldAbort = 0;
(將其聲明爲「volatile」是非常重要的,否則編譯器會發現沒有人在循環中寫入它,可能會認爲如果(g_shouldAbort)總是錯誤且opti邁茲它扔掉)
然後,使用例如信號 API其他用戶的建議,你可以這樣做:
void signal_handler(int sig_code)
{
if (sig_code == SIGUSR1) // user-defined signal 1
g_shouldAbort = 1;
}
(您需要註冊,當然這個處理程序,比照here。
signal(SIGUSR, signal_handler);
然後,當你「送」的SIGUSR1信號給你的程序(與殺例如命令),g_shouldAbort將被設置爲1,你的程序將停止其計算。
希望得到這個幫助!
注意:這種技術很簡單,但粗糙。正如其他用戶所概述的那樣,使用信號和全局變量使得難以使用多線程。
使用signal(2)
或sigaction(2)
爲函數指針分配SIGINT
信號,並在那裏進行清理。
你想要做的並不是微不足道的。您可以先使用signal
或sigaction
安裝SIGINT(C-c)的信號處理程序,但之後會啓動硬件部分。
主要問題是,在信號處理程序中,您只能調用async-signal-safe functions(或reentrant函數)。大多數庫函數不能可靠地被認爲是可重入的。例如,stdio
函數,malloc
,free
和許多其他不可重入。
那麼你如何處理呢?在你的處理程序中設置一個flag
(將一些全局變量done
設置爲1
)並查找EINTR
錯誤。在處理器之外進行清理應該是安全的。
讓你在你保存功能
// somewhere in main
signal(SIGTERM, signalHandler);
signal(SIGINT, signalHandler);
void saveMyData()
{
// save some data here
}
void signalHandler(int signalNumber)
{
static pthread_once_t semaphore = PTHREAD_ONCE_INIT;
std::cout << "signal " << signalNumber << " received." << std::endl;
pthread_once(& semaphore, saveMyData);
}
只輸入一次,如果你的進程中取得2點以上的信號,你寫完你的文件,你可以節省怪異數據
你想什麼之前確實屬於檢查點/重新啓動的範疇。
在檢查點/重啓時使用信號驅動方案有幾個大問題。一個是信號處理器必須非常緊湊和非常原始。您不能在信號處理程序中寫入檢查點。另一個問題是當信號發送時,你的程序可以在任何地方處於其執行狀態。這個隨機位置幾乎可以肯定不是一個安全點,檢查點可以從這個位置丟棄。還有一個問題是,您需要爲您的程序提供一些應用程序端檢查點/重新啓動功能。
而不是滾動自己的檢查點/重新啓動功能,我建議你看看使用一個已經存在的免費檢查點。 Linux上的gdb提供了檢查點/重新啓動功能。另一種是DMTCP,參見http://dmtcp.sourceforge.net/index.html。
for C++你可以考慮boost :: call_once – Nelstaar