2013-06-15 4 views
0

У меня есть программа для записи на C. Он должен создать 3 процесса, которые работают все время. Эти 3 процесса принимают сигналы (остановка, пауза, возобновление), когда он получает один из этих сигналов, он посылает другой сигнал остальным процессам, а затем записывает в трубу (это должен быть канал), какой сигнал он получает. Другие получают этот сигнал и читают трубку и выполняют то, что сказано в трубе. у меня есть что-то подобное, чтобы написать трубу в обработчике:Linux C связь между процессами с использованием сигналов и труб

void rcvkillsig(int sig){ 
    if(sig==SIGINT){ 
    int op; 
    op = 1; 
    close(pfd1[0]); 
    close(pfd3[0]); 
    write(pfd1[1], &op, 8); 
    write(pfd3[1], &op, 8); 
    close(pfd1[1]); 
    close(pfd3[1]); 
    kill(sndpid, SIGCONT); 
    kill(rcvpid, SIGCONT); 
    printf("End chk\n"); 
    kill(chkpid, SIGKILL); 
    } 
} 

И что-то подобное для чтения трубы:

void rcvinfsig(int sig){   
    if(sig==SIGCONT){ 
    cflag=0; 
    int op; 
    close(pfd2[1]); 
    read(pfd2[0], &op, 8); 
    close(pfd2[0]); 
    if(op==1){ 
     kill(chkpid, SIGKILL); 
     printf("End chk\n"); 
    } 
    else if(op==2){ 
     printf("Pause chk!\n"); 
     cpaused=1; 
    } 
    else if(op==3){ 
     printf("Resume chk!\n"); 
     cpaused=0; 
    } 
    } 
} 

Конечно, есть коды, как, что для каждого процесса, и принятый сигнал ,

Я использую в этой программе pfd1 [2], pfd2 [2], pfd3 [2] для каждого процесса и в основной функции создает для них трубы по каналу (...).

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

Пожалуйста, помогите, мне нужна эта программа в понедельник. Остальная часть кода работает, и у меня нет только этого сообщения.

ответ

0

Основываясь на опубликованных функциях, я думаю, что в вашем коде есть две основные проблемы.

1. Вы закрываете дескрипторы файлов при каждом вызове обработчика сигналов.

Неплохая идея - закрыть дескрипторы файлов каждый раз после чтения или записи. Однонаправленные трубы не работают таким образом. После создания дескрипторов пары вы должны закрыть первый дескриптор в один процесс и второй в другом процессе. Это создаст трубу от первого процесса до второго (man pipe). В примере с man-страницы они закрывают дескриптор справа после записи, потому что они больше не нужны.

2. Похоже, у вас есть только 3 пары дескрипторов файлов.

Для подключения 3 процессов, с помощью однонаправленных труб (как показано на рисунке ниже), требует 6 пар дескрипторов:

    fd 5,6     
    +------------+   +------------+ 
    |   |<----------|   | 
    | process #0 |   | process #1 | 
    |   |---------->|   | 
    +------------+   +------------+  
     | ^ fd 7,8  | ^   
     | |     | |   
fd 1,2 | | fd 3,4 fd 9,10 | | fd 11,12 
     | |     | |    
     v |     | |    
    +------------+    | |    
    |   |<--------------+ | 
    | process #2 |     | 
    |   |-------------------+ 
    +------------+        

Пример.

Здесь приведен пример кода, который делает то же самое. Это далеко от хорошего примера (обработка плохих сигналов, printf в обработчике сигналов), но я надеюсь, что это поможет немного.

int g_pfd[3][2][2]; // pairs of file desriptors. 

volatile sig_atomic_t g_ignore_sighup = 0; // flag for ignoring SIGHUP 

void (* g_handlers[3]) (int); // array of signal handlers 

void sig_handler (int signo, int id) 
{ 
    if (signo == SIGHUP) 
    { 
     if (g_ignore_sighup) 
     { 
      g_ignore_sighup = 0; 
      return; 
     } 

     printf ("SIGHUP recvd, pid = %d\n", getpid()); 

     int rd1 = (id); 
     int rd2 = (id == 0 ? 2 : id - 1); 

     // choose, which process sent SIGHUP. 

     fd_set rfds; 
     FD_ZERO (&rfds); 
     FD_SET (g_pfd[rd1][1][0], &rfds); 
     FD_SET (g_pfd[rd2][0][0], &rfds); 

     int rv = select (FD_SETSIZE, &rfds, NULL, NULL, NULL); 

     if (rv == -1) 
     { 
      perror ("select"); 
      return; 
     } 
     else if (rv == 0) 
     { 
      return; 
     } 

     int fd = -1; 
     if (FD_ISSET (g_pfd[rd1][1][0], &rfds)) fd = g_pfd[rd1][1][0]; 
     if (FD_ISSET (g_pfd[rd2][0][0], &rfds)) fd = g_pfd[rd2][0][0]; 

     int i; 

     if (read (fd, &i, sizeof (int)) == -1) 
     { 
      perror ("read"); 
     } 

     printf ("recvd data through pipe = %d\n", i); 
     return; 
    } 

    if (signo == SIGINT) 
    { 
     int wr1 = (id); 
     int wr2 = (id == 0 ? 2 : id - 1); 

     printf ("SIGINT recvd, pid = %d\n", getpid()); 
     printf ("write: %d to %d\n", getpid(), g_pfd[wr1][0][1]); 
     printf ("write: %d to %d\n", getpid(), g_pfd[wr2][1][1]); 

     int pid = getpid(); 
     if (write (g_pfd[wr1][0][1], &pid, sizeof (int)) == -1 || 
      write (g_pfd[wr2][1][1], &pid, sizeof (int)) == -1) 
     { 
      perror ("write"); 
     } 

     g_ignore_sighup = 1; // flag for ignorig own signal 

     // send SIGHUP to parent and all its children. 

     if (kill (0, SIGHUP) == -1) 
     { 
      perror ("kill"); 
     } 

     return; 
    } 
} 

void sig_handler_0 (int signo) { sig_handler (signo, 0); } 
void sig_handler_1 (int signo) { sig_handler (signo, 1); } 
void sig_handler_2 (int signo) { sig_handler (signo, 2); } 

int create_process (int *pid, int id) 
{ 
    *pid = fork(); 

    if (*pid == -1) 
    { 
     perror ("fork"); 
     return 1; 
    } 

    if (*pid != 0) // parent 
    { 
     return 0; 
    } 

    // close appropriate descriptors 

    int i1 = (id); 
    int i2 = (id == 0 ? 2 : id - 1); 

    close (g_pfd[i1][0][0]); 
    close (g_pfd[i2][0][1]); 
    close (g_pfd[i1][1][1]); 
    close (g_pfd[i2][1][0]); 

    if (signal (SIGINT, g_handlers[id]) == SIG_ERR || 
     signal (SIGHUP, g_handlers[id]) == SIG_ERR) 
    { 
     perror ("signal"); 
     return 1; 
    } 

    while (1) sleep (1); 
    exit (0); 
} 

int main (int argc, char *argv []) 
{ 
    // fill array of signal handlers. 

    g_handlers[0] = sig_handler_0; 
    g_handlers[1] = sig_handler_1; 
    g_handlers[2] = sig_handler_2; 

    if (signal (SIGHUP, SIG_IGN) == SIG_ERR) 
    { 
     perror ("signal"); 
     return 1;  
    } 

    int pid [3]; 
    int i, j; 

    // create pairs of descriptors 

    for (i = 0; i < 3; i++) 
    { 
     for (j = 0; j < 2; j++) 
     { 
      if (pipe (g_pfd[i][j]) == -1) 
      { 
       perror ("pipe"); 
       return 1; 
      } 
     } 
    } 

    if (create_process (&pid[0], 0) != 0 || 
     create_process (&pid[1], 1) != 0 || 
     create_process (&pid[2], 2) != 0) 
    { 
     return 1; 
    } 

    sleep (1); 

    kill (pid[0], SIGINT); sleep (3); 
    kill (pid[1], SIGINT); sleep (3); 
    kill (pid[2], SIGINT); 
    wait (NULL); 

    for (i = 0; i < 3; i++) 
    { 
     for (j = 0; j < 2; j++) 
     { 
      close (g_pfd[i][j][0]); 
      close (g_pfd[i][j][1]); 
     } 
    } 

    return 0; 
} 
+0

Спасибо за это, я надеюсь, что это сработает для меня. – manveruPL

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