我目前正在開發一個具有共享記憶體和信號量的程式。但是我在初始化它們時遇到問題。每當我想打開它們時(雖然 O_EXCL 標志處于活動狀態,但我一直在出錯。這應該意味著它們在開始時已經打開,但我不知道如何或為什么。
static sem_t *s1 = NULL;
void initSEM(void)
{
atexit(closeSEM);
s1 = sem_open(SEM_1, O_CREAT | O_EXCL, 0600, 1);
if (s1 == SEM_FAILED)
{
printf("%s", "ERROR: Semaphore 1 could not be opened.");
exit(EXIT_FAILURE);
}
}
void closeSEM(void)
{
if (sem_close(s1) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_close(s2) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_close(s3) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_1) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_2) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_2) == -1)
{
exit(EXIT_FAILURE);
}
}
在我的主要功能中,我只是稱之為。共享記憶體也是一樣。我不知道為什么會這樣。
uj5u.com熱心網友回復:
您撰寫的代碼只需要打開單個信號量一次就失敗,從那時起,將永遠不會正確地打開sem_unlink 任何信號量,因此它們將繼續存在以供下一次程式運行。
事件的順序是:
- 在開發的某個時刻,
sem_open無論出于何種原因都失敗了 - 相應的
sem_close失敗,那么,你exit(EXIT_FAILURE);,而不是執行任何余下的sem_close通話和所有的的sem_unlink電話,所以命名信號量繼續存在 - 在以后的運行中,所有
sem_open帶有O_CREAT/ 的呼叫都O_EXCL失敗(因為它們都沒有被取消鏈接),并且問題永遠不會得到解決
最簡單的解決方案是洗掉所有exit(EXIT_FAILURE);呼叫(也許用除錯日志替換它們);如果程式以其他方式成功運行完成,則清理失敗并不那么重要;確保執行所有清理比在某些清理失敗時快速失敗更重要。
atexit為每個命名的信號量注冊單獨的處理程式也可能是有意義的,并且只有在 sem_open該信號量成功之后,因此打開一個信號量不會為所有信號量注冊清除函式,打開失敗也不會導致您安排清除。這樣做將通過將清理限制在需要的情況下來減少在常見故障情況下預期的故障數量。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/359333.html
上一篇:MySql.Datawith'newThread'vsThreadPool:使用ThreadPool會造成死鎖
下一篇:C 執行緒工廠
