2016-11-11 39 views
1

私は、親プロセスが(子プロセスごとに1つの)名前のないセマフォの配列を使用して、複数の子プロセスがシグナルを送るのを待っています。 sem_wait()は、sem_wait()を使用すると、親プロセスが無期限に待機し、sem_trywait()は「リソースが一時的に使用できません」というエラーを返し、子プロセスがシグナルを出すことなく続行します。 sem_init()もsem_post()もエラーを返しません。コードの理由が「リソースは一時的に利用できません」

Relevent部分:

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_wait()は、子プロセスがwaitの前または後にsem_post()を呼び出すかどうかに関係なくエラーを検出します。

+0

多分私は何かが不足しているかもしれませんが、一見するとsem_wait()がsem_post()の後に呼び出されるようには見えないので、待つことはありません。たぶん私はコードをあまりにも速く読んでいますが、ここで私が読んでいることがあります:最初のループが 'pid == 0'条件に遭遇することなく完全に通り、' isChild'はまだfalseであるので、 'else' if(isChild) 'ケースをバイパスします。しかし、ポストは 'if(isChild)'ブロックにあるので、ポストされずにすぐに待機します。 – Scorch

+0

@ imp903 pidは 'fork()'によって返され、値は親に返されたforkによって作成された子のプロセスID、または子に返された0です。 'if(isChild)'ブロック内のすべては子プロセスによって実行され、 'else'ブロックは親プロセスによって実行されます。 printステートメントはすべて実行されるため、正常に動作しています。 – rangermattos

答えて

0

sem_t* sems = new sem_t[numsems];で割り当てられたセマフォは、共有メモリにありません。したがって、各プロセスには独自のコピーがあり、子への投稿は親に影響しません。

親のコピーはロックされたままです。 sem_trywaitEAGAINで失敗し、これはresource temporarily unavailableの説明に変換されます。

+0

私はこれを知らなかったとは信じられない、ありがとう。私が見てきたチュートリアルでは、共有メモリにセマフォを格納する必要はありません。 – rangermattos

関連する問題