2013-11-10 3 views
2

Я хочу создать N детей из родителя. Я хочу, чтобы все дети начали (функция - измерять время) одновременно. Поэтому я помещаю функцию в обработчик сигнала, и когда родительский закончить создание (fork) всех дочерних элементов, он отправляет сигнал (используя kill (children_id)) всем детям, чтобы начать старт. Код ниже, но он не работает должным образом. В частности, он разветвлял всех детей, но не выполняет функцию «measure_time» вообще. Эта функция не делает, а записывает время выполнения и распечатывает. Может ли кто-нибудь сообщить мне, если я что-то делаю неправильно?Сделайте процесс обработки детей до получения сигнала родителя

int n_task = 4; 
    for (i = 0; i < n_task; i++){ 
      pid = fork(); 
      if (pid < 0){ 
        printf("cannot fork!\n"); 
      } else 
      if (pid == 0){ //child 
        printf("printed from child [%d]\n", getpid());       
        signal(SIGUSR1, measure_time); //measure_time is a function 
        exit(0); 
      } else { 
        pid_array[i] = pid; 
      } 
    } 

    //This code is executed from parent only 
    for (int i = 0; i < n_task; i++) 
    { 
      kill(pid_array[i], SIGUSR1);     
    } 
+0

Любая причина, по которой вы используете 'fork()', а не pthreads? –

+0

@jeffamaphone: это упражнение, которое требует использования 'fork()' и 'signal()' или 'sigaction()' и 'kill()'? Вероятно, достаточная причина. –

+0

Да, я просто пытаюсь играть с fork(). – Zk1001

ответ

7
if (pid == 0){ //child 
    printf("printed from child [%d]\n", getpid());       
    signal(SIGUSR1, measure_time); //measure_time is a function 
    exit(0); 
} 

Дети получают созданы, устанавливается обработчик, и немедленно выйти (т.е. матрицы). Заставьте их спать или заблокировать что-то, поэтому настало время для родителя доставить сигналы.

Update

#define _POSIX_SOURCE 

#include <stdio.h> 
#include <errno.h> 
#include <unistd.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

void measure_time(int sig) 
{ 
    printf("child [%d] received signal %d\n", getpid(), sig); 
} 

int main(int argc, char *argv[]) 
{ 
    int n_task = 4; 

    pid_t pid; 
    pid_t pid_array[n_task]; 

    for (int i = 0; i < n_task; i++) 
    { 
     pid = fork(); 

     if (pid < 0) 
     { 
      perror("fork"); 
      exit(1); 
     } 

     if (pid == 0) //child 
     { 
      printf("printed from child [%d]\n", getpid()); 
      signal(SIGUSR1, measure_time); //measure_time is a function 
      sleep(5); 

      exit(0); 
     } 

     //parent 
     pid_array[i] = pid; 
    }  

    //This code is executed from parent only 
    sleep(1); 

    for (int i = 0; i < n_task; i++) 
     kill(pid_array[i], SIGUSR1); 

    for (int i = 0; i < n_task; i++) 
     wait(NULL);  

    return (0); 
} 

Все процессы и потоки подвержены капризам планировщиком операционной системы. В вашем исходном коде дети и родитель может прекратить действие до того, как последовательность событий, которые вы надеетесь провести, когда-нибудь случится. Дети могут умереть, прежде чем родитель когда-нибудь отправит сигнал; родитель может отправлять свои сигналы до того, как дети когда-либо установили свой обработчик (и SIGUSR1 убьет процесс, потому что это его значение по умолчанию при отсутствии обработчика). Существует так мало кода, чтобы выполнить все это происходит в миллисекундах, меньше времени, чем любой из этих процессов получает запланированное выполнение (и, таким образом, настройка достаточно для выполнения ваших ожиданий). Я добавил sleep, чтобы дать ему всю комнату для передышки и wait, чтобы родитель не умер. Это должно позволить вам увидеть, как это работает.

+0

Функция ['pause()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html) - это классический и самый простой способ дождаться появления сигнала. Он никогда не возвращается нормально; он только когда-либо возвращается, когда сигнал прерывает его. –

+0

Пробовал свой код. Но это не приводит к запуску всех четырех задач одновременно. Чтобы быть более конкретным, я добавил sleep (1) в measure_time(). Дети печатают свой «принятый сигнал» на основе 1 секунды. Не могли бы вы дать ему еще одну попытку? – Zk1001

+0

Я отредактировал родительский код kill/wait на 2 цикла. Возможно, это то, что вы видели. Приношу свои извинения за то, что вы были короткими. Даже не закончил мой утренний кофе. – Duck

1
if (pid == 0){ //child 
    printf("printed from child [%d]\n", getpid());       
    signal(SIGUSR1, measure_time); //measure_time is a function 
    pause(); 
    exit(0); 
} 

Я думаю, проблема в том, что дочерние процессы прекращаются сразу после их создания. поэтому
Используйте pause() Функция ожидания сигнала.

И если некоторые дочерние процессы не будут реагировать так, как ожидалось, попробуйте это также.

for (j = 0; j < n_task; j++) 
    { 
      kill(pid_array[j], SIGUSR1); 
      sleep(1); 
    } 
+0

Это похоже на ответ Утки, поэтому я прокомментирую здесь. Я пробовал это, но из 4 потоков был создан только 1 (иногда) 2 потока. Есть еще что-то не хватает? – Zk1001

+0

для (j = 0; j Deadlock

+0

Но это не поможет вам достичь своей цели, начать (функция - измерить время) в то же время от всех детей. Но все дочерние процессы будут выполнены. – Deadlock

Смежные вопросы