2016-11-11 60 views
1

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

+0

也许我错过了一些东西,但乍一看它并不像sem_wait()在sem_post()之后被调用,所以没有什么可以等待的。也许我只是快速阅读代码,但这里是我正在阅读的内容:如果第一个循环完全没有遇到'pid == 0'条件,'isChild'仍然是false,所以它直接到'else'的情况下,绕过'if(isChild)'的情况。但是由于该帖子位于'if(isChild)'块中,因此它会立即等待,无需发布。 – Scorch

+0

@ imp903 pid由'fork()'返回,并且该值是由返回到父级的分叉创建的子级的进程ID,或返回给子级的0。因此'if(isChild)'块内的所有内容都由子进程执行,而else块则由父进程执行。打印语句全部执行,因此工作正常。 – rangermattos

回答

0

分配为sem_t* sems = new sem_t[numsems];的信号量不在共享内存中。因此,每个进程都有自己的副本,并且在子级中发布不会影响父级。

家长的副本保持锁定状态。 sem_trywaitEAGAIN失败,这转换为resource temporarily unavailable解释。

+0

我不敢相信我没有意识到这一点,谢谢。我看过的教程都没有要求将信号量存储在共享内存中。 – rangermattos