我试图让一个父进程等待多个子进程发出信号,在父继续之前,使用未命名的信号量(每个子进程一个)数组。但是,当使用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