2016-11-11 61 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