2016-11-11 7 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_wait() встречает ошибку независимо от того, обрабатывает ли дочерний процесс вызов sem_post() до или после ожидания.

+0

Возможно, мне что-то не хватает, но на первый взгляд кажется, что sem_wait() никогда не будет вызван после sem_post(), так что ждать нечего. Возможно, я просто прочитал код слишком быстро, но вот что я читаю: если первый цикл проходит полностью, не сталкиваясь с условием 'pid == 0',' isChild' по-прежнему остается ложным, поэтому он переходит прямо в 'else' case, минуя 'if (isChild)' case. Но поскольку сообщение находится в блоке 'if (isChild)', он будет немедленно ждать, не будучи отправленным. – Scorch

+0

@ imp903 pid возвращается 'fork()', а значение представляет собой идентификатор процесса дочернего элемента, созданного вилкой, возвращаемой родительскому элементу, или 0 возвращается ребенку. Таким образом, все внутри блока 'if (isChild)' выполняется дочерними процессами, а блок 'else' выполняется родителем. Операторы печати выполняются, так что все работает нормально. – rangermattos

ответ

0

Семафоры, выделенные sem_t* sems = new sem_t[numsems];, не находятся в общей памяти. Поэтому каждый процесс имеет свою собственную копию, а публикация в дочернем файле не влияет на родителя.

Копия родителя остается заблокированной. sem_trywait с ошибкой EAGAIN, что соответствует resource temporarily unavailable пояснениям.

+0

Не могу поверить, что я этого не осознавал, спасибо. Ни один из обучающих программ, на которые я смотрел, не требует семафоров для хранения в общей памяти. – rangermattos