我試圖讓一個父進程等待多個子進程發出信號,在父繼續之前,使用未命名的信號量(每個子進程一個)數組。但是,當使用sem_wait()時,父進程將無限期等待,而sem_trywait()返回「資源暫時不可用」錯誤,並且在沒有發送子進程的情況下繼續。 sem_init()和sem_post()都不返回錯誤。代碼信號量未能等待,原因「資源暫時不可用」
培訓相關部分:
int numsems = concurrent_instrs.size();
std::cout << "Num sems: " << numsems << "\n";
// create semaphores
sem_t* sems = new sem_t[numsems];
for (int i = 0; i < numsems; i++)
{
if (sem_init(&sems[i], 1, 0) < 0)
{
perror("sem initialization failed");
exit(1);
}
}
int child_num = 0;
// perform all calculations in block concurrently
for(unsigned int i = 0; i < concurrent_instrs.size() && !isChild; i++)
{
int pid = fork();
if (pid == -1)
{
perror("Error forking:");
exit(1);
}
if (pid == 0)
{
isChild = true;
instr = concurrent_instrs[i];
}
else
{
child_num++;
}
}
if (isChild)
{
std::cout << "Child process " << child_num << " calculating: " << instr << "\n";
perform_calculation(instr, input_vars, internal_vars, shm_input, shm_internal);
std::cout << "Child process " << child_num << " finished calculating\n";
if (sem_post(&sems[child_num]) < 0)
{
perror("Child signal failed");
}
std::cout << "Child "<< child_num << " signalled\n";
// detach from shared memory
if (shmdt(shm_input) < 0)
{
perror("child shm_input detach failed");
}
if (shmdt(shm_internal) < 0)
{
perror("child shm_internal detach failed");
}
exit(0);
}
else
{
// parent waits for all children to finish
for (int i = 0; i < numsems; i++)
{
std::cout << "Waiting on subprocess " << i << " of " << numsems << "\n";
if (sem_trywait(&sems[i]) < 0)
perror("Parent wait failed");
else
std::cout << "Parent wait " << i << " working\n";
}
std::cout << "Finished waiting\n";
// destroy semaphores
for (int i = 0; i < numsems; i++)
{
if(sem_destroy(&sems[i]) < 0)
{
perror("Sem destroy failed");
exit(2);
}
else
{
std::cout << "Sem " << i << " destroyed\n";
}
}
delete[] sems;
}
難道我設置的東西了不正確,或者只是誤解如何在這種情況下使用信號燈?
編輯以添加:無論子進程在等待之前還是之後調用sem_post(),sem_wait()都會遇到錯誤。
也許我錯過了一些東西,但乍一看它並不像sem_wait()在sem_post()之後被調用,所以沒有什麼可以等待的。也許我只是快速閱讀代碼,但這裏是我正在閱讀的內容:如果第一個循環完全沒有遇到'pid == 0'條件,'isChild'仍然是false,所以它直接到'else'的情況下,繞過'if(isChild)'的情況。但是由於該帖子位於'if(isChild)'塊中,因此它會立即等待,無需發佈。 – Scorch
@ imp903 pid由'fork()'返回,並且該值是由返回到父級的分叉創建的子級的進程ID,或返回給子級的0。因此'if(isChild)'塊內的所有內容都由子進程執行,而else塊則由父進程執行。打印語句全部執行,因此工作正常。 – rangermattos