當我在寫一個使用定時器以固定的採樣率(200Hz的)做一些數據採集和處理應用程序中處理「intterupted系統調用」的錯誤。 應用程序像服務器一樣運行並在後臺運行。它應該可以從其他進程或來自UDP的其他機器進行控制。使用定時器
要做到這一點,我用timer_create()API定期生成SIGUSR1和調用完成的採集和處理的處理程序。
配置定時器的代碼是如下(爲了清楚減去錯誤校驗):
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCK_REALTIME, &sev, &timerid);
timer_settime(...)
當從UDP接收到「啓動」命令上面的代碼被調用。爲了檢查命令,我在調用recvfrom()系統調用的主程序中有一個無限循環。
問題是,當收到'start'命令,然後定時器正常啓動並運行(使用上面的代碼)時,由於SIGUSR1,我得到'中斷系統調用'錯誤(EINTR)定時器發送的信號中斷了recvfrom()調用。如果我檢查這個特定的錯誤代碼並忽略它,當調用recvfrom()時,我終於得到'連接被拒絕'錯誤。
所以在這裏我的問題:
- 如何解決這個「中斷的系統調用」的錯誤,因爲它似乎 忽略它,重新做recvfrom的()不工作?
- 爲什麼在大約20次嘗試後出現「連接被拒絕」錯誤?
- 我有一種感覺,使用SIGEV_THREAD可能是一個解決方案,我的理解是,創建一個新的線程(如phread_create)不產生信號。我對嗎?
- 信號號碼在這裏很重要嗎?使用實時信號還有什麼優點?
- 是否有任何其他的方式做什麼,我打算做的:具有從UDP和實時週期任務後臺循環檢查命令?
而且這裏的獎金問題:
- 它是安全的進行數據採集和處理的處理程序或我應該使用一個信號量機制來喚醒一個線程,這樣做?
解決方案: 作爲一個答案,並在評論中建議,使用SA_RESTART似乎解決的主要問題。
解決方案2: 通過SIGEV_SIGNAL使用SIGEV_THREAD也起作用。我讀過使用SIGEV_THREAD可能需要比SIGEV_SIGNAL更多的資源的地方。但是,我沒有看到有關任務時間的重大差異。
我並不完全瞭解你的情況,但是避免在信號處理程序中做「真正的工作」的一種優雅方法是打開一個管道到自身,讓信號處理程序寫入管道,並讓main選擇循環(我猜你有一個)從管道讀取並做真正的工作。我不知道這是否能滿足您的時間需求。至少管道避免了併發問題,因爲從管道讀取和寫入是原子的(並且在它們之間存在上下文切換),這也避免了需要連續切換sigmask。 – wildplasser 2012-07-26 20:04:43
我不確定我是否理解了你的所有問題,但是你可以嘗試將'SA_RESTART'添加到'sa_flags'嗎? – ninjalj 2012-07-26 20:12:41
wildplasser>我沒有任何選擇循環,因爲我只有一件事要做:檢查通過帶有'recvfrom' – pahpaul 2012-07-26 22:38:52